]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/late.rs
resolve: Populate external modules in more automatic and lazy way
[rust.git] / src / librustc_resolve / late.rs
index 7cb11195ee02ba0538dcf2ae06a8877c1969d5a7..d8bd86699b7af966982543c6143c77599f8d110d 100644 (file)
@@ -1,3 +1,10 @@
+//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros.
+//! It runs when the crate is fully expanded and its module structure is fully built.
+//! So it just walks through the crate and resolves all the expressions, types, etc.
+//!
+//! If you wonder why there's no `early.rs`, that's because it's split into three files -
+//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
+
 use GenericParameters::*;
 use RibKind::*;
 
@@ -352,7 +359,7 @@ fn visit_ty(&mut self, ty: &'tcx Ty) {
                 self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
             }
             TyKind::ImplicitSelf => {
-                let self_ty = Ident::with_empty_ctxt(kw::SelfUpper);
+                let self_ty = Ident::with_dummy_span(kw::SelfUpper);
                 let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span)
                               .map_or(Res::Err, |d| d.res());
                 self.r.record_partial_res(ty.id, PartialRes::new(res));
@@ -442,7 +449,7 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
                 GenericParamKind::Type { ref default, .. } => {
                     found_default |= default.is_some();
                     if found_default {
-                        Some((Ident::with_empty_ctxt(param.ident.name), Res::Err))
+                        Some((Ident::with_dummy_span(param.ident.name), Res::Err))
                     } else {
                         None
                     }
@@ -459,7 +466,7 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
                     false
                 }
             })
-            .map(|param| (Ident::with_empty_ctxt(param.ident.name), Res::Err)));
+            .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err)));
 
         for param in &generics.params {
             match param.kind {
@@ -476,7 +483,7 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
                     }
 
                     // Allow all following defaults to refer to this type parameter.
-                    default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
+                    default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
                 GenericParamKind::Const { ref ty } => {
                     self.ribs[TypeNS].push(const_ty_param_ban_rib);
@@ -501,8 +508,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
     fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
         // During late resolution we only track the module component of the parent scope,
         // although it may be useful to track other components as well for diagnostics.
-        let parent_scope = resolver.dummy_parent_scope();
         let graph_root = resolver.graph_root;
+        let parent_scope = ParentScope::module(graph_root);
         LateResolutionVisitor {
             r: resolver,
             parent_scope,
@@ -574,7 +581,6 @@ fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
-            self.r.finalize_current_module_macro_resolutions(module);
             let ret = f(self);
 
             self.parent_scope.module = orig_module;
@@ -965,7 +971,7 @@ fn with_self_rib<F>(&mut self, self_res: Res, f: F)
         let mut self_type_rib = Rib::new(NormalRibKind);
 
         // Plain insert (no renaming, since types are not currently hygienic)
-        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
         self.ribs[TypeNS].push(self_type_rib);
         f(self);
         self.ribs[TypeNS].pop();
@@ -976,7 +982,7 @@ fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
     {
         let self_res = Res::SelfCtor(impl_id);
         let mut self_type_rib = Rib::new(NormalRibKind);
-        self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
         self.ribs[ValueNS].push(self_type_rib);
         f(self);
         self.ribs[ValueNS].pop();
@@ -1136,65 +1142,53 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
     // Checks that all of the arms in an or-pattern have exactly the
     // same set of bindings, with the same binding modes for each.
     fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
-        if pats.is_empty() {
-            return;
-        }
-
         let mut missing_vars = FxHashMap::default();
         let mut inconsistent_vars = FxHashMap::default();
-        for (i, p) in pats.iter().enumerate() {
-            let map_i = self.binding_mode_map(&p);
-
-            for (j, q) in pats.iter().enumerate() {
-                if i == j {
-                    continue;
-                }
 
-                let map_j = self.binding_mode_map(&q);
-                for (&key, &binding_i) in &map_i {
-                    if map_j.is_empty() {                   // Account for missing bindings when
-                        let binding_error = missing_vars    // `map_j` has none.
-                            .entry(key.name)
-                            .or_insert(BindingError {
-                                name: key.name,
-                                origin: BTreeSet::new(),
-                                target: BTreeSet::new(),
-                            });
-                        binding_error.origin.insert(binding_i.span);
-                        binding_error.target.insert(q.span);
-                    }
-                    for (&key_j, &binding_j) in &map_j {
-                        match map_i.get(&key_j) {
-                            None => {  // missing binding
-                                let binding_error = missing_vars
-                                    .entry(key_j.name)
-                                    .or_insert(BindingError {
-                                        name: key_j.name,
-                                        origin: BTreeSet::new(),
-                                        target: BTreeSet::new(),
-                                    });
-                                binding_error.origin.insert(binding_j.span);
-                                binding_error.target.insert(p.span);
-                            }
-                            Some(binding_i) => {  // check consistent binding
-                                if binding_i.binding_mode != binding_j.binding_mode {
-                                    inconsistent_vars
-                                        .entry(key.name)
-                                        .or_insert((binding_j.span, binding_i.span));
-                                }
+        for pat_outer in pats.iter() {
+            let map_outer = self.binding_mode_map(&pat_outer);
+
+            for pat_inner in pats.iter().filter(|pat| pat.id != pat_outer.id) {
+                let map_inner = self.binding_mode_map(&pat_inner);
+
+                for (&key_inner, &binding_inner) in map_inner.iter() {
+                    match map_outer.get(&key_inner) {
+                        None => {  // missing binding
+                            let binding_error = missing_vars
+                                .entry(key_inner.name)
+                                .or_insert(BindingError {
+                                    name: key_inner.name,
+                                    origin: BTreeSet::new(),
+                                    target: BTreeSet::new(),
+                                    could_be_path:
+                                        key_inner.name.as_str().starts_with(char::is_uppercase)
+                                });
+                            binding_error.origin.insert(binding_inner.span);
+                            binding_error.target.insert(pat_outer.span);
+                        }
+                        Some(binding_outer) => {  // check consistent binding
+                            if binding_outer.binding_mode != binding_inner.binding_mode {
+                                inconsistent_vars
+                                    .entry(key_inner.name)
+                                    .or_insert((binding_inner.span, binding_outer.span));
                             }
                         }
                     }
                 }
             }
         }
-        let mut missing_vars = missing_vars.iter().collect::<Vec<_>>();
+
+        let mut missing_vars = missing_vars.iter_mut().collect::<Vec<_>>();
         missing_vars.sort();
-        for (_, v) in missing_vars {
+        for (name, mut v) in missing_vars {
+            if inconsistent_vars.contains_key(name) {
+                v.could_be_path = false;
+            }
             self.r.report_error(
-                *v.origin.iter().next().unwrap(), ResolutionError::VariableNotBoundInPattern(v)
-            );
+                *v.origin.iter().next().unwrap(),
+                ResolutionError::VariableNotBoundInPattern(v));
         }
+
         let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
         inconsistent_vars.sort();
         for (name, v) in inconsistent_vars {
@@ -1222,7 +1216,9 @@ fn resolve_pats(&mut self, pats: &[P<Pat>], source: PatternSource) {
             self.resolve_pattern(pat, source, &mut bindings_list);
         }
         // This has to happen *after* we determine which pat_idents are variants
-        self.check_consistent_bindings(pats);
+        if pats.len() > 1 {
+            self.check_consistent_bindings(pats);
+        }
     }
 
     fn resolve_block(&mut self, block: &Block) {
@@ -1237,7 +1233,6 @@ fn resolve_block(&mut self, block: &Block) {
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.parent_scope.module = anonymous_module;
-            self.r.finalize_current_module_macro_resolutions(anonymous_module);
         } else {
             self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
@@ -1486,7 +1481,7 @@ fn smart_resolve_path_fragment(&mut self,
                     self.r.trait_map.insert(id, traits);
                 }
 
-                let mut std_path = vec![Segment::from_ident(Ident::with_empty_ctxt(sym::std))];
+                let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))];
                 std_path.extend(path);
                 if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) {
                     let cl = CrateLint::No;
@@ -1517,7 +1512,7 @@ fn smart_resolve_path_fragment(&mut self,
 
     fn self_type_is_available(&mut self, span: Span) -> bool {
         let binding = self.resolve_ident_in_lexical_scope(
-            Ident::with_empty_ctxt(kw::SelfUpper),
+            Ident::with_dummy_span(kw::SelfUpper),
             TypeNS,
             None,
             span,
@@ -1934,7 +1929,7 @@ fn get_traits_in_module_containing_item(&mut self,
         let mut traits = module.traits.borrow_mut();
         if traits.is_none() {
             let mut collected_traits = Vec::new();
-            module.for_each_child(|name, ns, binding| {
+            module.for_each_child(self.r, |_, name, ns, binding| {
                 if ns != TypeNS { return }
                 match binding.res() {
                     Res::Def(DefKind::Trait, _) |
@@ -1994,7 +1989,6 @@ fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>,
 
 impl<'a> Resolver<'a> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
-        self.finalize_current_module_macro_resolutions(self.graph_root);
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.unused_labels.iter() {