]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/resolve_imports.rs
Refactor away separate tracking of used_public and used_reexport.
[rust.git] / src / librustc_resolve / resolve_imports.rs
index 3d2300e44c46893484a9f0ef897856089a26f4da..54dcd0001c4a5ee409be361f19af8874d7fafde4 100644 (file)
 use self::ImportDirectiveSubclass::*;
 
 use DefModifiers;
-use DefOrModule;
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
-use NameBinding;
+use {NameBinding, NameBindingKind};
 use ResolveResult;
 use ResolveResult::*;
 use Resolver;
@@ -78,23 +77,25 @@ pub fn new(module_path: Vec<Name>,
             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,
-}
+    // 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, binding: &'a NameBinding<'a>) -> NameBinding<'a> {
+        let mut modifiers = match self.is_public {
+            true => DefModifiers::PUBLIC | DefModifiers::IMPORTABLE,
+            false => DefModifiers::empty(),
+        };
+        if let GlobImport = self.subclass {
+            modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
+        }
+        if self.shadowable == Shadowable::Always {
+            modifiers = modifiers | DefModifiers::PRELUDE;
+        }
 
-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,
+        NameBinding {
+            kind: NameBindingKind::Import { binding: binding, id: self.id },
+            span: Some(self.span),
+            modifiers: modifiers,
         }
     }
 }
@@ -117,7 +118,7 @@ pub struct ImportResolution<'a> {
     pub is_public: bool,
 
     /// Resolution of the name in the namespace
-    pub target: Option<Target<'a>>,
+    pub binding: Option<&'a NameBinding<'a>>,
 
     /// The source node of the `use` directive
     pub id: NodeId,
@@ -128,14 +129,16 @@ pub fn new(id: NodeId, is_public: bool) -> Self {
         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(binding) if binding.defined_with(DefModifiers::PRELUDE) =>
+                Shadowable::Always,
+            Some(_) => Shadowable::Never,
             None => Shadowable::Always,
         }
     }
@@ -203,7 +206,7 @@ fn resolve_imports(&mut self) {
 
     /// Resolves an `ImportResolvingError` into the correct enum discriminant
     /// and passes that on to `resolve_error`.
-    fn import_resolving_error(&self, e: ImportResolvingError) {
+    fn import_resolving_error(&self, e: ImportResolvingError<'b>) {
         // If it's a single failed import then create a "fake" import
         // resolution for it so that later resolve stages won't complain.
         if let SingleImport(target, _) = e.import_directive.subclass {
@@ -217,23 +220,17 @@ fn import_resolving_error(&self, e: ImportResolvingError) {
                                       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 = self.resolver.new_name_binding(NameBinding {
                     modifiers: DefModifiers::IMPORTABLE,
-                    def_or_module: DefOrModule::Def(Def::Err),
+                    kind: NameBindingKind::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 +371,13 @@ fn resolve_import_for_module(&mut self,
     }
 
     /// 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.
     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<&'b NameBinding<'b>> {
         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,33 +386,32 @@ fn resolve_name_in_module(&mut self,
                     self.resolver.used_crates.insert(krate);
                 }
             }
-            return (Success((module, name_binding)), false)
+            return Success(name_binding);
         }
 
         // If there is an unresolved glob at this point in the containing module, bail out.
         // We don't know enough to be able to resolve the name.
         if module.pub_glob_count.get() > 0 {
-            return (Indeterminate, false);
+            return Indeterminate;
         }
 
         match module.import_resolutions.borrow().get(&(name, ns)) {
             // The containing module definitely doesn't have an exported import with the
             // name in question. We can therefore accurately report that names are unbound.
-            None => (Failed(None), false),
+            None => Failed(None),
 
             // The name is an import which has been fully resolved, so we just follow it.
             Some(resolution) if resolution.outstanding_references == 0 => {
                 // Import resolutions must be declared with "pub" in order to be exported.
                 if !resolution.is_public {
-                    return (Failed(None), false);
+                    return Failed(None);
                 }
 
-                let target = resolution.target.clone();
-                if let Some(Target { target_module, binding, shadowable: _ }) = target {
+                if let Some(binding) = resolution.binding {
                     self.resolver.record_import_use(name, ns, &resolution);
-                    (Success((target_module, binding)), true)
+                    Success(binding)
                 } else {
-                    (Failed(None), false)
+                    Failed(None)
                 }
             }
 
@@ -431,8 +426,8 @@ fn resolve_name_in_module(&mut self,
             // In this case we continue as if we resolved the import and let
             // check_for_conflicts_between_imports_and_items handle the conflict
             Some(_) => match (importing_module.def_id(), module.def_id()) {
-                (Some(id1), Some(id2)) if id1 == id2 => (Failed(None), false),
-                _ => (Indeterminate, false)
+                (Some(id1), Some(id2)) if id1 == id2 => Failed(None),
+                _ => Indeterminate
             },
         }
     }
@@ -464,15 +459,15 @@ fn resolve_single_import(&mut self,
         };
 
         // We need to resolve both namespaces for this to succeed.
-        let (value_result, value_used_reexport) =
+        let value_result =
             self.resolve_name_in_module(target_module, source, ValueNS, module_);
-        let (type_result, type_used_reexport) =
+        let type_result =
             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(name_binding), _) if !name_binding.is_import() &&
+                                           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 +476,7 @@ fn resolve_single_import(&mut self,
                     .emit();
             }
 
-            (_, &Success((_, ref name_binding))) if !type_used_reexport &&
-                                                    directive.is_public => {
+            (_, &Success(name_binding)) if !name_binding.is_import() && directive.is_public => {
                 if !name_binding.is_public() {
                     let msg = format!("`{}` is private, and cannot be reexported", source);
                     let note_msg =
@@ -526,15 +520,12 @@ fn resolve_single_import(&mut self,
             _ => (),
         }
 
-        let mut value_used_public = false;
-        let mut type_used_public = false;
-
         // We've successfully resolved the import. Write the results in.
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
 
         {
-            let mut check_and_write_import = |namespace, result, used_public: &mut bool| {
-                let result: &ResolveResult<(Module<'b>, NameBinding)> = result;
+            let mut check_and_write_import = |namespace, result| {
+                let result: &ResolveResult<&NameBinding> = result;
 
                 let import_resolution = import_resolutions.get_mut(&(target, namespace)).unwrap();
                 let namespace_name = match namespace {
@@ -543,7 +534,7 @@ fn resolve_single_import(&mut self,
                 };
 
                 match *result {
-                    Success((ref target_module, ref name_binding)) => {
+                    Success(name_binding) => {
                         debug!("(resolving single import) found {:?} target: {:?}",
                                namespace_name,
                                name_binding.def());
@@ -556,14 +547,12 @@ fn resolve_single_import(&mut self,
                                                              directive.span,
                                                              target);
 
-                        import_resolution.target = Some(Target::new(target_module,
-                                                                    name_binding.clone(),
-                                                                    directive.shadowable));
+                        import_resolution.binding =
+                            Some(self.resolver.new_name_binding(directive.import(name_binding)));
                         import_resolution.id = directive.id;
                         import_resolution.is_public = directive.is_public;
 
                         self.add_export(module_, target, &import_resolution);
-                        *used_public = name_binding.is_public();
                     }
                     Failed(_) => {
                         // Continue.
@@ -578,8 +567,8 @@ fn resolve_single_import(&mut self,
                                                                    directive.span,
                                                                    (target, namespace));
             };
-            check_and_write_import(ValueNS, &value_result, &mut value_used_public);
-            check_and_write_import(TypeNS, &type_result, &mut type_used_public);
+            check_and_write_import(ValueNS, &value_result);
+            check_and_write_import(TypeNS, &type_result);
         }
 
         if let (&Failed(_), &Failed(_)) = (&value_result, &type_result) {
@@ -589,9 +578,6 @@ fn resolve_single_import(&mut self,
             return Failed(Some((directive.span, msg)));
         }
 
-        let value_used_public = value_used_reexport || value_used_public;
-        let type_used_public = type_used_reexport || type_used_public;
-
         let value_def_and_priv = {
             let import_resolution_value = import_resolutions.get_mut(&(target, ValueNS)).unwrap();
             assert!(import_resolution_value.outstanding_references >= 1);
@@ -600,9 +586,9 @@ fn resolve_single_import(&mut self,
             // 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();
-                let last_private = if value_used_public { lp } else { DependsOn(def.def_id()) };
+            import_resolution_value.binding.as_ref().map(|binding| {
+                let def = binding.def().unwrap();
+                let last_private = if binding.is_public() { lp } else { DependsOn(def.def_id()) };
                 (def, last_private)
             })
         };
@@ -612,9 +598,9 @@ fn resolve_single_import(&mut self,
             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();
-                let last_private = if type_used_public { lp } else { DependsOn(def.def_id()) };
+            import_resolution_type.binding.as_ref().map(|binding| {
+                let def = binding.def().unwrap();
+                let last_private = if binding.is_public() { lp } else { DependsOn(def.def_id()) };
                 (def, last_private)
             })
         };
@@ -695,15 +681,16 @@ fn resolve_glob_import(&mut self,
                 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(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(self.resolver.new_name_binding(import_directive.import(binding)));
                     self.add_export(module_, name, &dest_import_resolution);
                 }
                 _ => {}
@@ -718,7 +705,7 @@ fn resolve_glob_import(&mut self,
                                          target_module,
                                          import_directive,
                                          (name, ns),
-                                         name_binding.clone());
+                                         name_binding);
         });
 
         // Record the destination of this import
@@ -740,7 +727,7 @@ fn merge_import_resolution(&mut self,
                                containing_module: Module<'b>,
                                import_directive: &ImportDirective,
                                (name, ns): (Name, Namespace),
-                               name_binding: NameBinding<'b>) {
+                               name_binding: &'b NameBinding<'b>) {
         let id = import_directive.id;
         let is_public = import_directive.is_public;
 
@@ -778,10 +765,8 @@ fn merge_import_resolution(&mut self,
                                  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(self.resolver.new_name_binding(import_directive.import(name_binding)));
                 dest_import_resolution.id = id;
                 dest_import_resolution.is_public = is_public;
                 self.add_export(module_, name, &dest_import_resolution);
@@ -800,7 +785,7 @@ fn add_export(&mut self, module: Module<'b>, name: Name, resolution: &ImportReso
             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 +798,16 @@ fn check_for_conflicting_import(&mut self,
                                     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(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 +861,8 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         };
 
         if ns == ValueNS {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
+            match import.binding {
+                Some(binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
                     let mut err = struct_span_err!(self.resolver.session,
                                                    import_span,
                                                    E0255,
@@ -892,8 +877,8 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
                 Some(_) | None => {}
             }
         } else {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
+            match import.binding {
+                Some(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}::*`?)",