]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_resolve/src/access_levels.rs
Rollup merge of #103543 - ehuss:update-books, r=ehuss
[rust.git] / compiler / rustc_resolve / src / access_levels.rs
index 1cef60949d81249927a4026353d212971a181ee3..c27b5b0c420072e8ce6d6d7d5828f8279535ed99 100644 (file)
@@ -1,5 +1,4 @@
-use crate::NameBindingKind;
-use crate::Resolver;
+use crate::{ImportKind, NameBindingKind, Resolver};
 use rustc_ast::ast;
 use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
@@ -45,14 +44,13 @@ fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
         let module = self.r.get_module(module_id.to_def_id()).unwrap();
         let resolutions = self.r.resolutions(module);
 
-        for (key, name_resolution) in resolutions.borrow().iter() {
+        for (_, name_resolution) in resolutions.borrow().iter() {
             if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() {
                 // Set the given binding access level to `AccessLevel::Public` and
                 // sets the rest of the `use` chain to `AccessLevel::Exported` until
                 // we hit the actual exported item.
 
-                // FIXME: tag and is_public() condition must be deleted,
-                // but assertion fail occurs in import_id_for_ns
+                // FIXME: tag and is_public() condition should be removed, but assertions occur.
                 let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public };
                 if binding.vis.is_public() {
                     let mut prev_parent_id = module_id;
@@ -60,16 +58,26 @@ fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
                     while let NameBindingKind::Import { binding: nested_binding, import, .. } =
                         binding.kind
                     {
-                        let id = self.r.local_def_id(self.r.import_id_for_ns(import, key.ns));
-                        self.update(
-                            id,
+                        let mut update = |node_id| self.update(
+                            self.r.local_def_id(node_id),
                             binding.vis.expect_local(),
                             prev_parent_id,
                             level,
                         );
+                        // In theory all the import IDs have individual visibilities and effective
+                        // visibilities, but in practice these IDs go straigth to HIR where all
+                        // their few uses assume that their (effective) visibility applies to the
+                        // whole syntactic `use` item. So we update them all to the maximum value
+                        // among the potential individual effective visibilities. Maybe HIR for
+                        // imports shouldn't use three IDs at all.
+                        update(import.id);
+                        if let ImportKind::Single { additional_ids, .. } = import.kind {
+                            update(additional_ids.0);
+                            update(additional_ids.1);
+                        }
 
                         level = AccessLevel::Exported;
-                        prev_parent_id = id;
+                        prev_parent_id = self.r.local_def_id(import.id);
                         binding = nested_binding;
                     }
                 }
@@ -88,10 +96,18 @@ fn update(
         parent_id: LocalDefId,
         tag: AccessLevel,
     ) {
+        let module_id = self
+            .r
+            .get_nearest_non_block_module(def_id.to_def_id())
+            .nearest_parent_mod()
+            .expect_local();
+        if nominal_vis == Visibility::Restricted(module_id)
+            || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id)
+        {
+            return;
+        }
         let mut access_levels = std::mem::take(&mut self.r.access_levels);
-        let module_id =
-            self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local();
-        let res = access_levels.update(
+        self.changed |= access_levels.update(
             def_id,
             nominal_vis,
             || Visibility::Restricted(module_id),
@@ -99,14 +115,6 @@ fn update(
             tag,
             &*self.r,
         );
-        if let Ok(changed) = res {
-            self.changed |= changed;
-        } else {
-            self.r.session.delay_span_bug(
-                self.r.opt_span(def_id.to_def_id()).unwrap(),
-                "Can't update effective visibility",
-            );
-        }
         self.r.access_levels = access_levels;
     }
 }