]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/resolve_imports.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / librustc_resolve / resolve_imports.rs
index 189253348b0aa9aaab0f3986168ddc7f8c4d434f..875d6745f6b2e26f7c5da2d45d0a0f5052a570db 100644 (file)
@@ -55,6 +55,7 @@ pub enum ImportDirectiveSubclass<'a> {
     GlobImport {
         is_prelude: bool,
         max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
+        // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
     },
 }
 
@@ -181,7 +182,9 @@ pub fn resolve_name_in_module(&mut self,
                 if is_disallowed_private_import(binding) {
                     return Failed(None);
                 }
-                self.record_use(name, ns, binding);
+                if self.record_use(name, ns, binding, span) {
+                    return Success(self.dummy_binding);
+                }
                 if !self.is_accessible(binding.vis) {
                     self.privacy_errors.push(PrivacyError(span, name, binding));
                 }
@@ -317,10 +320,28 @@ pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, b
         where T: ToNameBinding<'a>
     {
         let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
-        self.update_resolution(module, name, ns, |_, resolution| {
+        self.update_resolution(module, name, ns, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
                 if binding.is_glob_import() {
-                    resolution.duplicate_globs.push(binding);
+                    if !this.new_import_semantics || !old_binding.is_glob_import() {
+                        resolution.duplicate_globs.push(binding);
+                    } else if binding.def() != old_binding.def() {
+                        resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding {
+                            kind: NameBindingKind::Ambiguity {
+                                b1: old_binding,
+                                b2: binding,
+                            },
+                            vis: if old_binding.vis.is_at_least(binding.vis, this) {
+                                old_binding.vis
+                            } else {
+                                binding.vis
+                            },
+                            span: old_binding.span,
+                        }));
+                    } else if !old_binding.vis.is_at_least(binding.vis, this) {
+                        // We are glob-importing the same item but with greater visibility.
+                        resolution.binding = Some(binding);
+                    }
                 } else if old_binding.is_glob_import() {
                     resolution.duplicate_globs.push(old_binding);
                     resolution.binding = Some(binding);
@@ -344,20 +365,26 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
         // during which the resolution might end up getting re-defined via a glob cycle.
         let (binding, t) = {
             let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
-            let was_known = resolution.binding().is_some();
+            let old_binding = resolution.binding();
 
             let t = f(self, resolution);
 
-            if was_known { return t; }
             match resolution.binding() {
-                Some(binding) => (binding, t),
+                _ if !self.new_import_semantics && old_binding.is_some() => return t,
                 None => return t,
+                Some(binding) => match old_binding {
+                    Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
+                    _ => (binding, t),
+                }
             }
         };
 
         // Define `binding` in `module`s glob importers.
-        if binding.vis == ty::Visibility::Public {
-            for directive in module.glob_importers.borrow_mut().iter() {
+        for directive in module.glob_importers.borrow_mut().iter() {
+            if match self.new_import_semantics {
+                true => self.is_accessible_from(binding.vis, directive.parent),
+                false => binding.vis == ty::Visibility::Public,
+            } {
                 let imported_binding = self.import(binding, directive);
                 let _ = self.try_define(directive.parent, name, ns, imported_binding);
             }
@@ -434,7 +461,7 @@ fn resolve_imports(&mut self) {
                 errors = true;
                 let (span, help) = match err {
                     Some((span, msg)) => (span, msg),
-                    None => (import.span, String::new()),
+                    None => continue,
                 };
 
                 // If the error is a single failed import then create a "fake" import
@@ -584,7 +611,10 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
 
         for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
             if let Ok(binding) = result {
-                self.record_use(name, ns, binding);
+                if self.record_use(name, ns, binding, directive.span) {
+                    self.resolution(module, name, ns).borrow_mut().binding =
+                        Some(self.dummy_binding);
+                }
             }
         }
 
@@ -708,7 +738,8 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
             resolution.borrow().binding().map(|binding| (*name, binding))
         }).collect::<Vec<_>>();
         for ((name, ns), binding) in bindings {
-            if binding.pseudo_vis() == ty::Visibility::Public {
+            if binding.pseudo_vis() == ty::Visibility::Public ||
+               self.new_import_semantics && self.is_accessible(binding.vis) {
                 let imported_binding = self.import(binding, directive);
                 let _ = self.try_define(directive.parent, name, ns, imported_binding);
             }
@@ -745,17 +776,16 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                         }
                     }
 
-                    self.report_conflict(module, name, ns, duplicate_glob, binding);
-                }
-            } else if binding.is_glob_import() {
-                for duplicate_glob in resolution.duplicate_globs.iter() {
                     self.report_conflict(module, name, ns, duplicate_glob, binding);
                 }
             }
 
             if binding.vis == ty::Visibility::Public &&
                (binding.is_import() || binding.is_extern_crate()) {
-                reexports.push(Export { name: name, def_id: binding.def().def_id() });
+                let def = binding.def();
+                if def != Def::Err {
+                    reexports.push(Export { name: name, def_id: def.def_id() });
+                }
             }
 
             if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {