about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/lib.rs56
-rw-r--r--src/librustc_resolve/resolve_imports.rs114
2 files changed, 75 insertions, 95 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3fcf14bbbcd..b2f60ddb8da 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -92,8 +92,7 @@ use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::mem::replace;
 
-use resolve_imports::{Target, ImportDirective, ImportResolution};
-use resolve_imports::Shadowable;
+use resolve_imports::{ImportDirective, ImportResolution};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -951,6 +950,7 @@ bitflags! {
         // Variants are considered `PUBLIC`, but some of them live in private enums.
         // We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
         const PRIVATE_VARIANT = 1 << 2,
+        const PRELUDE = 1 << 3,
     }
 }
 
@@ -1291,10 +1291,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                            name);
                     return Indeterminate;
                 }
-                Success((target, used_proxy)) => {
+                Success((binding, used_proxy)) => {
                     // Check to see whether there are type bindings, and, if
                     // so, whether there is a module within.
-                    if let Some(module_def) = target.binding.module() {
+                    if let Some(module_def) = binding.module() {
                         search_module = module_def;
 
                         // Keep track of the closest private module used
@@ -1390,7 +1390,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 debug!("(resolving module path for import) indeterminate; bailing");
                                 return Indeterminate;
                             }
-                            Success((target, _)) => match target.binding.module() {
+                            Success((binding, _)) => match binding.module() {
                                 Some(containing_module) => {
                                     search_module = containing_module;
                                     start_index = 1;
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                      name: Name,
                                      namespace: Namespace,
                                      record_used: bool)
-                                     -> ResolveResult<(Target<'a>, bool)> {
+                                     -> ResolveResult<(NameBinding<'a>, bool)> {
         debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
                name,
                namespace,
@@ -1446,10 +1446,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     debug!("(resolving item in lexical scope) indeterminate higher scope; bailing");
                     return Indeterminate;
                 }
-                Success((target, used_reexport)) => {
+                Success((binding, used_reexport)) => {
                     // We found the module.
                     debug!("(resolving item in lexical scope) found name in module, done");
-                    return Success((target, used_reexport));
+                    return Success((binding, used_reexport));
                 }
             }
 
@@ -1543,7 +1543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     /// Attempts to resolve the supplied name in the given module for the
-    /// given namespace. If successful, returns the target corresponding to
+    /// given namespace. If successful, returns the binding corresponding to
     /// the name.
     ///
     /// The boolean returned on success is an indicator of whether this lookup
@@ -1554,7 +1554,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                               namespace: Namespace,
                               allow_private_imports: bool,
                               record_used: bool)
-                              -> ResolveResult<(Target<'a>, bool)> {
+                              -> ResolveResult<(NameBinding<'a>, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                name,
                module_to_string(&*module_));
@@ -1570,7 +1570,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     self.used_crates.insert(krate);
                 }
             }
-            return Success((Target::new(module_, binding, Shadowable::Never), false));
+            return Success((binding, false));
         }
 
         // Check the list of resolved imports.
@@ -1580,12 +1580,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     debug!("(resolving name in module) import unresolved; bailing out");
                     return Indeterminate;
                 }
-                if let Some(target) = import_resolution.target.clone() {
+                if let Some(binding) = import_resolution.binding.clone() {
                     debug!("(resolving name in module) resolved to import");
                     if record_used {
                         self.record_import_use(name, namespace, &import_resolution);
                     }
-                    return Success((target, true));
+                    return Success((binding, true));
                 }
             }
             Some(..) | None => {} // Continue.
@@ -2616,11 +2616,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                        -> BareIdentifierPatternResolution {
         let module = self.current_module;
         match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
-            Success((target, _)) => {
+            Success((binding, _)) => {
                 debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
                        name,
-                       &target.binding);
-                match target.binding.def() {
+                       &binding);
+                match binding.def() {
                     None => {
                         panic!("resolved name in the value namespace to a set of name bindings \
                                 with no def?!");
@@ -2776,7 +2776,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let module = self.current_module;
         let name = identifier.unhygienic_name;
         match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
-            Success((target, _)) => target.binding.def().map(LocalDef::from_def),
+            Success((binding, _)) => binding.def().map(LocalDef::from_def),
             Failed(Some((span, msg))) => {
                 resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
                 None
@@ -2914,7 +2914,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let name = segments.last().unwrap().identifier.name;
         let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
         let def = match result {
-            Success((Target { binding, .. }, _)) => {
+            Success((binding, _)) => {
                 let (def, lp) = binding.def_and_lp();
                 (def, last_private.or(lp))
             }
@@ -2970,7 +2970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         let name = segments.last().unwrap().identifier.name;
         match self.resolve_name_in_module(containing_module, name, namespace, false, true) {
-            Success((Target { binding, .. }, _)) => {
+            Success((binding, _)) => {
                 let (def, lp) = binding.def_and_lp();
                 Some((def, last_private.or(lp)))
             }
@@ -3008,12 +3008,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
-                if let Success((target, _)) = self.resolve_name_in_module(module,
-                                                                          ident.unhygienic_name,
-                                                                          namespace,
-                                                                          true,
-                                                                          true) {
-                    if let Some(def) = target.binding.def() {
+                if let Success((binding, _)) = self.resolve_name_in_module(module,
+                                                                           ident.unhygienic_name,
+                                                                           namespace,
+                                                                           true,
+                                                                           true) {
+                    if let Some(def) = binding.def() {
                         return Some(LocalDef::from_def(def));
                     }
                 }
@@ -3455,11 +3455,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             // Look for imports.
             for (&(_, ns), import) in search_module.import_resolutions.borrow().iter() {
                 if ns != TypeNS { continue }
-                let target = match import.target {
-                    Some(ref target) => target,
+                let binding = match import.binding {
+                    Some(ref binding) => binding,
                     None => continue,
                 };
-                let did = match target.binding.def() {
+                let did = match binding.def() {
                     Some(Def::Trait(trait_def_id)) => trait_def_id,
                     Some(..) | None => continue,
                 };
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 3d2300e44c4..882531efbb7 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -78,24 +78,14 @@ impl ImportDirective {
             shadowable: shadowable,
         }
     }
-}
-
-/// The item that an import resolves to.
-#[derive(Clone,Debug)]
-pub struct Target<'a> {
-    pub target_module: Module<'a>,
-    pub binding: NameBinding<'a>,
-    pub shadowable: Shadowable,
-}
 
-impl<'a> Target<'a> {
-    pub fn new(target_module: Module<'a>, binding: NameBinding<'a>, shadowable: Shadowable)
-               -> Self {
-        Target {
-            target_module: target_module,
-            binding: binding,
-            shadowable: shadowable,
+    // Given the binding to which this directive resolves in a particular namespace,
+    // this returns the binding for the name this directive defines in that namespace.
+    fn import<'a>(&self, mut binding: NameBinding<'a>) -> NameBinding<'a> {
+        if self.shadowable == Shadowable::Always {
+            binding.modifiers = binding.modifiers | DefModifiers::PRELUDE;
         }
+        binding
     }
 }
 
@@ -117,7 +107,7 @@ pub struct ImportResolution<'a> {
     pub is_public: bool,
 
     /// Resolution of the name in the namespace
-    pub target: Option<Target<'a>>,
+    pub binding: Option<NameBinding<'a>>,
 
     /// The source node of the `use` directive
     pub id: NodeId,
@@ -128,14 +118,16 @@ impl<'a> ImportResolution<'a> {
         ImportResolution {
             outstanding_references: 0,
             id: id,
-            target: None,
+            binding: None,
             is_public: is_public,
         }
     }
 
     pub fn shadowable(&self) -> Shadowable {
-        match self.target {
-            Some(ref target) => target.shadowable,
+        match self.binding {
+            Some(ref binding) if binding.defined_with(DefModifiers::PRELUDE) =>
+                Shadowable::Always,
+            Some(_) => Shadowable::Never,
             None => Shadowable::Always,
         }
     }
@@ -217,23 +209,17 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                       e.import_directive.is_public)
             });
 
-            if resolution.target.is_none() {
+            if resolution.binding.is_none() {
                 debug!("(resolving import error) adding fake target to import resolution of `{}`",
                        target);
 
-                let name_binding = NameBinding {
+                let dummy_binding = NameBinding {
                     modifiers: DefModifiers::IMPORTABLE,
                     def_or_module: DefOrModule::Def(Def::Err),
                     span: None,
                 };
 
-                // Create a fake target pointing to a fake name binding in our
-                // own module
-                let target = Target::new(e.source_module,
-                                         name_binding,
-                                         Shadowable::Always);
-
-                resolution.target = Some(target);
+                resolution.binding = Some(dummy_binding);
             }
         }
 
@@ -374,14 +360,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
     }
 
     /// Resolves the name in the namespace of the module because it is being imported by
-    /// importing_module. Returns the module in which the name was defined (as opposed to imported),
-    /// the name bindings defining the name, and whether or not the name was imported into `module`.
+    /// importing_module. Returns the name bindings defining the name
+    /// and whether or not the name was imported.
     fn resolve_name_in_module(&mut self,
                               module: Module<'b>, // Module containing the name
                               name: Name,
                               ns: Namespace,
                               importing_module: Module<'b>) // Module importing the name
-                              -> (ResolveResult<(Module<'b>, NameBinding<'b>)>, bool) {
+                              -> (ResolveResult<NameBinding<'b>>, bool) {
         build_reduced_graph::populate_module_if_necessary(self.resolver, module);
         if let Some(name_binding) = module.get_child(name, ns) {
             if name_binding.is_extern_crate() {
@@ -390,7 +376,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     self.resolver.used_crates.insert(krate);
                 }
             }
-            return (Success((module, name_binding)), false)
+            return (Success(name_binding), false)
         }
 
         // If there is an unresolved glob at this point in the containing module, bail out.
@@ -411,10 +397,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     return (Failed(None), false);
                 }
 
-                let target = resolution.target.clone();
-                if let Some(Target { target_module, binding, shadowable: _ }) = target {
+                if let Some(binding) = resolution.binding.clone() {
                     self.resolver.record_import_use(name, ns, &resolution);
-                    (Success((target_module, binding)), true)
+                    (Success(binding), true)
                 } else {
                     (Failed(None), false)
                 }
@@ -470,9 +455,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             self.resolve_name_in_module(target_module, source, TypeNS, module_);
 
         match (&value_result, &type_result) {
-            (&Success((_, ref name_binding)), _) if !value_used_reexport &&
-                                                    directive.is_public &&
-                                                    !name_binding.is_public() => {
+            (&Success(ref name_binding), _) if !value_used_reexport &&
+                                               directive.is_public &&
+                                               !name_binding.is_public() => {
                 let msg = format!("`{}` is private, and cannot be reexported", source);
                 let note_msg = format!("Consider marking `{}` as `pub` in the imported module",
                                         source);
@@ -481,8 +466,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     .emit();
             }
 
-            (_, &Success((_, ref name_binding))) if !type_used_reexport &&
-                                                    directive.is_public => {
+            (_, &Success(ref name_binding)) if !type_used_reexport &&
+                                               directive.is_public => {
                 if !name_binding.is_public() {
                     let msg = format!("`{}` is private, and cannot be reexported", source);
                     let note_msg =
@@ -534,7 +519,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
         {
             let mut check_and_write_import = |namespace, result, used_public: &mut bool| {
-                let result: &ResolveResult<(Module<'b>, NameBinding)> = result;
+                let result: &ResolveResult<NameBinding> = result;
 
                 let import_resolution = import_resolutions.get_mut(&(target, namespace)).unwrap();
                 let namespace_name = match namespace {
@@ -543,7 +528,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                 };
 
                 match *result {
-                    Success((ref target_module, ref name_binding)) => {
+                    Success(ref name_binding) => {
                         debug!("(resolving single import) found {:?} target: {:?}",
                                namespace_name,
                                name_binding.def());
@@ -556,9 +541,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                                              directive.span,
                                                              target);
 
-                        import_resolution.target = Some(Target::new(target_module,
-                                                                    name_binding.clone(),
-                                                                    directive.shadowable));
+                        import_resolution.binding = Some(directive.import(name_binding.clone()));
                         import_resolution.id = directive.id;
                         import_resolution.is_public = directive.is_public;
 
@@ -600,8 +583,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             // Record what this import resolves to for later uses in documentation,
             // this may resolve to either a value or a type, but for documentation
             // purposes it's good enough to just favor one over the other.
-            import_resolution_value.target.as_ref().map(|target| {
-                let def = target.binding.def().unwrap();
+            import_resolution_value.binding.as_ref().map(|binding| {
+                let def = binding.def().unwrap();
                 let last_private = if value_used_public { lp } else { DependsOn(def.def_id()) };
                 (def, last_private)
             })
@@ -612,8 +595,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             assert!(import_resolution_type.outstanding_references >= 1);
             import_resolution_type.outstanding_references -= 1;
 
-            import_resolution_type.target.as_ref().map(|target| {
-                let def = target.binding.def().unwrap();
+            import_resolution_type.binding.as_ref().map(|binding| {
+                let def = binding.def().unwrap();
                 let last_private = if type_used_public { lp } else { DependsOn(def.def_id()) };
                 (def, last_private)
             })
@@ -695,15 +678,15 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                 import_resolutions.entry((name, ns))
                                   .or_insert_with(|| ImportResolution::new(id, is_public));
 
-            match target_import_resolution.target {
-                Some(ref target) if target_import_resolution.is_public => {
+            match target_import_resolution.binding {
+                Some(ref binding) if target_import_resolution.is_public => {
                     self.check_for_conflicting_import(&dest_import_resolution,
                                                       import_directive.span,
                                                       name,
                                                       ns);
                     dest_import_resolution.id = id;
                     dest_import_resolution.is_public = is_public;
-                    dest_import_resolution.target = Some(target.clone());
+                    dest_import_resolution.binding = Some(import_directive.import(binding.clone()));
                     self.add_export(module_, name, &dest_import_resolution);
                 }
                 _ => {}
@@ -778,10 +761,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                  name);
                 span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg);
             } else {
-                let target = Target::new(containing_module,
-                                         name_binding.clone(),
-                                         import_directive.shadowable);
-                dest_import_resolution.target = Some(target);
+                dest_import_resolution.binding = Some(import_directive.import(name_binding.clone()));
                 dest_import_resolution.id = id;
                 dest_import_resolution.is_public = is_public;
                 self.add_export(module_, name, &dest_import_resolution);
@@ -800,7 +780,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             Some(def_id) => self.resolver.ast_map.as_local_node_id(def_id).unwrap(),
             None => return,
         };
-        let export = match resolution.target.as_ref().unwrap().binding.def() {
+        let export = match resolution.binding.as_ref().unwrap().def() {
             Some(def) => Export { name: name, def_id: def.def_id() },
             None => return,
         };
@@ -813,16 +793,16 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                     import_span: Span,
                                     name: Name,
                                     namespace: Namespace) {
-        let target = &import_resolution.target;
+        let binding = &import_resolution.binding;
         debug!("check_for_conflicting_import: {}; target exists: {}",
                name,
-               target.is_some());
+               binding.is_some());
 
-        match *target {
-            Some(ref target) if target.shadowable != Shadowable::Always => {
+        match *binding {
+            Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
                 let ns_word = match namespace {
                     TypeNS => {
-                        match target.binding.module() {
+                        match binding.module() {
                             Some(ref module) if module.is_normal() => "module",
                             Some(ref module) if module.is_trait() => "trait",
                             _ => "type",
@@ -876,8 +856,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         };
 
         if ns == ValueNS {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
+            match import.binding {
+                Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
                     let mut err = struct_span_err!(self.resolver.session,
                                                    import_span,
                                                    E0255,
@@ -892,8 +872,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                 Some(_) | None => {}
             }
         } else {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
+            match import.binding {
+                Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
                     if name_binding.is_extern_crate() {
                         let msg = format!("import `{0}` conflicts with imported crate \
                                            in this module (maybe you meant `use {0}::*`?)",