]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Register new snapshots
[rust.git] / src / librustc_resolve / lib.rs
index b4e2d6beb8b8399ea13b031bbe2bfea186608bd2..5711807a6172f6f82928f79bf284ccb343bee3ff 100644 (file)
@@ -8,11 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
-#![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "rustc_resolve"]
 #![unstable(feature = "rustc_private", issue = "27812")]
-#![cfg_attr(stage0, staged_api)]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -64,7 +61,7 @@
 use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
 
 use syntax::ast;
-use syntax::ast::{CRATE_NODE_ID, Ident, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
+use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
 use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
 use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::{self, special_names, special_idents};
@@ -96,7 +93,7 @@
 use std::rc::{Rc, Weak};
 use std::usize;
 
-use resolve_imports::{Target, ImportDirective, ImportResolution};
+use resolve_imports::{Target, ImportDirective, ImportResolutionPerNamespace};
 use resolve_imports::Shadowable;
 
 // NB: This module needs to be declared first so diagnostics are
@@ -202,9 +199,18 @@ pub enum ResolutionError<'a> {
     AttemptToUseNonConstantValueInConstant,
 }
 
+/// Context of where `ResolutionError::UnresolvedName` arose.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub enum UnresolvedNameContext {
+    /// `PathIsMod(id)` indicates that a given path, used in
+    /// expression context, actually resolved to a module rather than
+    /// a value. The `id` attached to the variant is the node id of
+    /// the erroneous path expression.
     PathIsMod(ast::NodeId),
+
+    /// `Other` means we have no extra information about the context
+    /// of the unresolved name error. (Maybe we could eliminate all
+    /// such cases; but for now, this is an information-free default.)
     Other,
 }
 
@@ -334,7 +340,7 @@ fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                              .import_resolutions
                                              .borrow()
                                              .get(&name) {
-                let item = resolver.ast_map.expect_item(directive.value_id);
+                let item = resolver.ast_map.expect_item(directive.value_ns.id);
                 resolver.session.span_note(item.span, "constant imported here");
             }
         }
@@ -605,6 +611,7 @@ fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBound
             Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
             Err(_) => {
                 // error already reported
+                self.record_def(tref.trait_ref.ref_id, err_path_resolution())
             }
         }
         intravisit::walk_poly_trait_ref(self, tref, m);
@@ -832,7 +839,7 @@ pub struct Module {
     anonymous_children: RefCell<NodeMap<Rc<Module>>>,
 
     // The status of resolving each import in this module.
-    import_resolutions: RefCell<HashMap<Name, ImportResolution>>,
+    import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace>>,
 
     // The number of unresolved globs that this module exports.
     glob_count: Cell<usize>,
@@ -943,15 +950,20 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 bitflags! {
     #[derive(Debug)]
     flags DefModifiers: u8 {
+        // Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
+        // or `use Enum::*` to work on private enums.
         const PUBLIC     = 1 << 0,
         const IMPORTABLE = 1 << 1,
+        // 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,
     }
 }
 
 // Records a possibly-private value, type, or module definition.
 #[derive(Debug)]
 struct NsDef {
-    modifiers: DefModifiers, // see note in ImportResolution about how to use this
+    modifiers: DefModifiers, // see note in ImportResolutionPerNamespace about how to use this
     def_or_module: DefOrModule,
     span: Option<Span>,
 }
@@ -1501,7 +1513,8 @@ fn resolve_module_path(&mut self,
     fn resolve_item_in_lexical_scope(&mut self,
                                      module_: Rc<Module>,
                                      name: Name,
-                                     namespace: Namespace)
+                                     namespace: Namespace,
+                                     record_used: bool)
                                      -> ResolveResult<(Target, bool)> {
         debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
                name,
@@ -1530,7 +1543,7 @@ fn resolve_item_in_lexical_scope(&mut self,
         // adjacent import statements are processed as though they mutated the
         // current scope.
         if let Some(import_resolution) = module_.import_resolutions.borrow().get(&name) {
-            match (*import_resolution).target_for_namespace(namespace) {
+            match import_resolution[namespace].target.clone() {
                 None => {
                     // Not found; continue.
                     debug!("(resolving item in lexical scope) found import resolution, but not \
@@ -1540,11 +1553,13 @@ fn resolve_item_in_lexical_scope(&mut self,
                 Some(target) => {
                     debug!("(resolving item in lexical scope) using import resolution");
                     // track used imports and extern crates as well
-                    let id = import_resolution.id(namespace);
-                    self.used_imports.insert((id, namespace));
-                    self.record_import_use(id, name);
-                    if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
-                        self.used_crates.insert(kid);
+                    let id = import_resolution[namespace].id;
+                    if record_used {
+                        self.used_imports.insert((id, namespace));
+                        self.record_import_use(id, name);
+                        if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
+                            self.used_crates.insert(kid);
+                        }
                     }
                     return Success((target, false));
                 }
@@ -1621,7 +1636,7 @@ fn resolve_module_in_lexical_scope(&mut self,
                                        -> ResolveResult<Rc<Module>> {
         // If this module is an anonymous module, resolve the item in the
         // lexical scope. Otherwise, resolve the item from the crate root.
-        let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS);
+        let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
         match resolve_result {
             Success((target, _)) => {
                 if let Some(module_def) = target.binding.module() {
@@ -1751,13 +1766,15 @@ fn resolve_name_in_module(&mut self,
 
         // Check the list of resolved imports.
         match module_.import_resolutions.borrow().get(&name) {
-            Some(import_resolution) if allow_private_imports || import_resolution.is_public => {
+            Some(import_resolution) if allow_private_imports ||
+                                       import_resolution[namespace].is_public => {
 
-                if import_resolution.is_public && import_resolution.outstanding_references != 0 {
+                if import_resolution[namespace].is_public &&
+                   import_resolution.outstanding_references != 0 {
                     debug!("(resolving name in module) import unresolved; bailing out");
                     return Indeterminate;
                 }
-                match import_resolution.target_for_namespace(namespace) {
+                match import_resolution[namespace].target.clone() {
                     None => {
                         debug!("(resolving name in module) name found, but not in namespace {:?}",
                                namespace);
@@ -1765,7 +1782,7 @@ fn resolve_name_in_module(&mut self,
                     Some(target) => {
                         debug!("(resolving name in module) resolved to import");
                         // track used imports and extern crates as well
-                        let id = import_resolution.id(namespace);
+                        let id = import_resolution[namespace].id;
                         self.used_imports.insert((id, namespace));
                         self.record_import_use(id, name);
                         if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
@@ -2042,6 +2059,7 @@ fn resolve_item(&mut self, item: &Item) {
                                                   prefix.span,
                                                   ResolutionError::FailedToResolve(
                                                       &path_names_to_string(prefix, 0)));
+                                    self.record_def(item.id, err_path_resolution());
                                 }
                             }
                         }
@@ -2201,6 +2219,7 @@ fn resolve_generics(&mut self, generics: &Generics) {
                         resolve_error(self,
                                       eq_pred.span,
                                       ResolutionError::UndeclaredAssociatedType);
+                        self.record_def(eq_pred.id, err_path_resolution());
                     }
                 }
             }
@@ -2231,6 +2250,8 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
                 self.record_def(trait_ref.ref_id, path_res);
                 new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
                 new_id = Some(path_res.base_def.def_id());
+            } else {
+                self.record_def(trait_ref.ref_id, err_path_resolution());
             }
             intravisit::walk_trait_ref(self, trait_ref);
         }
@@ -2500,6 +2521,8 @@ fn resolve_type(&mut self, ty: &Ty) {
                         self.record_def(ty.id, def);
                     }
                     None => {
+                        self.record_def(ty.id, err_path_resolution());
+
                         // Keep reporting some errors even if they're ignored above.
                         self.resolve_path(ty.id, path, 0, TypeNS, true);
 
@@ -2582,6 +2605,7 @@ fn resolve_pattern(&mut self,
                                 ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
                                     renamed)
                             );
+                            self.record_def(pattern.id, err_path_resolution());
                         }
                         FoundConst(def, lp, _) if const_ok => {
                             debug!("(resolving pattern) resolving `{}` to constant", renamed);
@@ -2601,6 +2625,7 @@ fn resolve_pattern(&mut self,
                                 ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
                                                                                     name)
                             );
+                            self.record_def(pattern.id, err_path_resolution());
                         }
                         BareIdentifierPatternUnresolved => {
                             debug!("(resolving pattern) binding `{}`", renamed);
@@ -2684,6 +2709,7 @@ fn resolve_pattern(&mut self,
                                 resolve_error(&self,
                                               path.span,
                                               ResolutionError::StaticVariableReference);
+                                self.record_def(pattern.id, err_path_resolution());
                             }
                             _ => {
                                 // If anything ends up here entirely resolved,
@@ -2702,6 +2728,7 @@ fn resolve_pattern(&mut self,
                                                  .name
                                                  .as_str())
                                     );
+                                    self.record_def(pattern.id, err_path_resolution());
                                 } else {
                                     let const_name = path.segments
                                                          .last()
@@ -2721,6 +2748,7 @@ fn resolve_pattern(&mut self,
                             ResolutionError::UnresolvedEnumVariantStructOrConst(
                                 &path.segments.last().unwrap().identifier.name.as_str())
                         );
+                        self.record_def(pattern.id, err_path_resolution());
                     }
                     intravisit::walk_path(self, path);
                 }
@@ -2763,6 +2791,7 @@ fn resolve_pattern(&mut self,
                                         &path.segments.last().unwrap().identifier.name.as_str()
                                     )
                                 );
+                                self.record_def(pattern.id, err_path_resolution());
                             }
                         }
                     } else {
@@ -2774,6 +2803,7 @@ fn resolve_pattern(&mut self,
                                                                                       .identifier
                                                                                       .name
                                                                                       .as_str()));
+                        self.record_def(pattern.id, err_path_resolution());
                     }
                     intravisit::walk_pat(self, pattern);
                 }
@@ -2791,6 +2821,7 @@ fn resolve_pattern(&mut self,
                                 ResolutionError::DoesNotNameAStruct(
                                     &*path_names_to_string(path, 0))
                             );
+                            self.record_def(pattern.id, err_path_resolution());
                         }
                     }
                     intravisit::walk_path(self, path);
@@ -2813,7 +2844,7 @@ fn resolve_bare_identifier_pattern(&mut self,
                                        span: Span)
                                        -> BareIdentifierPatternResolution {
         let module = self.current_module.clone();
-        match self.resolve_item_in_lexical_scope(module, name, ValueNS) {
+        match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
             Success((target, _)) => {
                 debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
                        name,
@@ -2921,17 +2952,16 @@ pub fn resolve_path(&mut self,
         }
 
         // Try to find a path to an item in a module.
-        let unqualified_def = self.resolve_identifier(segments.last().unwrap().identifier,
-                                                      namespace,
-                                                      check_ribs);
-
+        let last_ident = segments.last().unwrap().identifier;
         if segments.len() <= 1 {
+            let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
             return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
                                   .map(|def| {
                                       PathResolution::new(def, LastMod(AllPublic), path_depth)
                                   });
         }
 
+        let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
         let def = self.resolve_module_relative_path(span, segments, namespace);
         match (def, unqualified_def) {
             (Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
@@ -2951,7 +2981,8 @@ pub fn resolve_path(&mut self,
     fn resolve_identifier(&mut self,
                           identifier: hir::Ident,
                           namespace: Namespace,
-                          check_ribs: bool)
+                          check_ribs: bool,
+                          record_used: bool)
                           -> Option<LocalDef> {
         // First, check to see whether the name is a primitive type.
         if namespace == TypeNS {
@@ -2968,7 +2999,8 @@ fn resolve_identifier(&mut self,
             }
         }
 
-        self.resolve_item_by_name_in_lexical_scope(identifier.unhygienic_name, namespace)
+        let name = identifier.unhygienic_name;
+        self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
             .map(LocalDef::from_def)
     }
 
@@ -3219,11 +3251,12 @@ fn resolve_identifier_in_local_ribs(&mut self,
 
     fn resolve_item_by_name_in_lexical_scope(&mut self,
                                              name: Name,
-                                             namespace: Namespace)
+                                             namespace: Namespace,
+                                             record_used: bool)
                                              -> Option<Def> {
         // Check the items.
         let module = self.current_module.clone();
-        match self.resolve_item_in_lexical_scope(module, name, namespace) {
+        match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
             Success((target, _)) => {
                 match target.binding.def() {
                     None => {
@@ -3467,6 +3500,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         } else {
                             self.session.span_help(expr.span, &msg);
                         }
+                        self.record_def(expr.id, err_path_resolution());
                     } else {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
@@ -3491,6 +3525,8 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     let type_res = self.with_no_errors(|this| {
                         this.resolve_path(expr.id, path, 0, TypeNS, false)
                     });
+
+                    self.record_def(expr.id, err_path_resolution());
                     match type_res.map(|r| r.base_def) {
                         Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
                             resolve_error(
@@ -3597,6 +3633,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                       ResolutionError::DoesNotNameAStruct(
                                                                 &*path_names_to_string(path, 0))
                                      );
+                        self.record_def(expr.id, err_path_resolution());
                     }
                 }
 
@@ -3619,6 +3656,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
                 match self.search_label(label.node.name) {
                     None => {
+                        self.record_def(expr.id, err_path_resolution());
                         resolve_error(self,
                                       label.span,
                                       ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
@@ -3710,9 +3748,9 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
 
             // Look for imports.
             for (_, import) in search_module.import_resolutions.borrow().iter() {
-                let target = match import.target_for_namespace(TypeNS) {
+                let target = match import.type_ns.target {
                     None => continue,
-                    Some(target) => target,
+                    Some(ref target) => target,
                 };
                 let did = match target.binding.def() {
                     Some(DefTrait(trait_def_id)) => trait_def_id,
@@ -3720,7 +3758,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
                     add_trait_info(&mut found_traits, did, name);
-                    let id = import.type_id;
+                    let id = import.type_ns.id;
                     self.used_imports.insert((id, TypeNS));
                     let trait_name = self.get_trait_name(did);
                     self.record_import_use(id, trait_name);
@@ -3793,7 +3831,7 @@ fn dump_module(&mut self, module_: Rc<Module>) {
         let import_resolutions = module_.import_resolutions.borrow();
         for (&name, import_resolution) in import_resolutions.iter() {
             let value_repr;
-            match import_resolution.target_for_namespace(ValueNS) {
+            match import_resolution.value_ns.target {
                 None => {
                     value_repr = "".to_string();
                 }
@@ -3804,7 +3842,7 @@ fn dump_module(&mut self, module_: Rc<Module>) {
             }
 
             let type_repr;
-            match import_resolution.target_for_namespace(TypeNS) {
+            match import_resolution.type_ns.target {
                 None => {
                     type_repr = "".to_string();
                 }
@@ -3868,6 +3906,14 @@ fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
     names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
 }
 
+fn err_path_resolution() -> PathResolution {
+    PathResolution {
+        base_def: DefErr,
+        last_private: LastMod(AllPublic),
+        depth: 0,
+    }
+}
+
 
 pub struct CrateMap {
     pub def_map: RefCell<DefMap>,
@@ -3893,7 +3939,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None);
 
     resolver.resolve_crate(krate);
-    session.abort_if_errors();
 
     check_unused::check_crate(&mut resolver, krate);