]> 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 e688857d038574094e338fe3911484675add6dc0..d8bd86699b7af966982543c6143c77599f8d110d 100644 (file)
@@ -1,10 +1,16 @@
+//! "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::*;
 
-use crate::{path_names_to_string, resolve_error};
-use crate::{AliasPossibility, BindingError, CrateLint, LexicalScopeBinding, Module};
-use crate::{ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
-use crate::{PathSource, ResolutionError, Resolver, Rib, RibKind, Segment, UseError};
-use crate::RibKind::*;
+use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
+use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
+use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use log::debug;
 use rustc::{bug, lint, span_bug};
@@ -24,7 +30,6 @@
 
 use std::collections::BTreeSet;
 use std::mem::replace;
-use std::ops::{Deref, DerefMut};
 
 mod diagnostics;
 
@@ -68,11 +73,235 @@ fn descr(self) -> &'static str {
     }
 }
 
+/// The rib kind restricts certain accesses,
+/// e.g. to a `Res::Local` of an outer item.
+#[derive(Copy, Clone, Debug)]
+crate enum RibKind<'a> {
+    /// No restriction needs to be applied.
+    NormalRibKind,
+
+    /// We passed through an impl or trait and are now in one of its
+    /// methods or associated types. Allow references to ty params that impl or trait
+    /// binds. Disallow any other upvars (including other ty params that are
+    /// upvars).
+    AssocItemRibKind,
+
+    /// We passed through a function definition. Disallow upvars.
+    /// Permit only those const parameters that are specified in the function's generics.
+    FnItemRibKind,
+
+    /// We passed through an item scope. Disallow upvars.
+    ItemRibKind,
+
+    /// We're in a constant item. Can't refer to dynamic stuff.
+    ConstantItemRibKind,
+
+    /// We passed through a module.
+    ModuleRibKind(Module<'a>),
+
+    /// We passed through a `macro_rules!` statement
+    MacroDefinition(DefId),
+
+    /// All bindings in this rib are type parameters that can't be used
+    /// from the default of a type parameter because they're not declared
+    /// before said type parameter. Also see the `visit_generics` override.
+    ForwardTyParamBanRibKind,
+
+    /// We forbid the use of type parameters as the types of const parameters.
+    TyParamAsConstParamTy,
+}
+
+/// A single local scope.
+///
+/// A rib represents a scope names can live in. Note that these appear in many places, not just
+/// around braces. At any place where the list of accessible names (of the given namespace)
+/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
+/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
+/// etc.
+///
+/// Different [rib kinds](enum.RibKind) are transparent for different names.
+///
+/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
+/// resolving, the name is looked up from inside out.
+#[derive(Debug)]
+crate struct Rib<'a, R = Res> {
+    pub bindings: FxHashMap<Ident, R>,
+    pub kind: RibKind<'a>,
+}
+
+impl<'a, R> Rib<'a, R> {
+    fn new(kind: RibKind<'a>) -> Rib<'a, R> {
+        Rib {
+            bindings: Default::default(),
+            kind,
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+crate enum AliasPossibility {
+    No,
+    Maybe,
+}
+
+#[derive(Copy, Clone, Debug)]
+crate enum PathSource<'a> {
+    // Type paths `Path`.
+    Type,
+    // Trait paths in bounds or impls.
+    Trait(AliasPossibility),
+    // Expression paths `path`, with optional parent context.
+    Expr(Option<&'a Expr>),
+    // Paths in path patterns `Path`.
+    Pat,
+    // Paths in struct expressions and patterns `Path { .. }`.
+    Struct,
+    // Paths in tuple struct patterns `Path(..)`.
+    TupleStruct,
+    // `m::A::B` in `<T as m::A>::B::C`.
+    TraitItem(Namespace),
+}
+
+impl<'a> PathSource<'a> {
+    fn namespace(self) -> Namespace {
+        match self {
+            PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
+            PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
+            PathSource::TraitItem(ns) => ns,
+        }
+    }
+
+    fn defer_to_typeck(self) -> bool {
+        match self {
+            PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
+            PathSource::Struct | PathSource::TupleStruct => true,
+            PathSource::Trait(_) | PathSource::TraitItem(..) => false,
+        }
+    }
+
+    fn descr_expected(self) -> &'static str {
+        match self {
+            PathSource::Type => "type",
+            PathSource::Trait(_) => "trait",
+            PathSource::Pat => "unit struct/variant or constant",
+            PathSource::Struct => "struct, variant or union type",
+            PathSource::TupleStruct => "tuple struct/variant",
+            PathSource::TraitItem(ns) => match ns {
+                TypeNS => "associated type",
+                ValueNS => "method or associated constant",
+                MacroNS => bug!("associated macro"),
+            },
+            PathSource::Expr(parent) => match parent.map(|p| &p.node) {
+                // "function" here means "anything callable" rather than `DefKind::Fn`,
+                // this is not precise but usually more helpful than just "value".
+                Some(&ExprKind::Call(..)) => "function",
+                _ => "value",
+            },
+        }
+    }
+
+    crate fn is_expected(self, res: Res) -> bool {
+        match self {
+            PathSource::Type => match res {
+                Res::Def(DefKind::Struct, _)
+                | Res::Def(DefKind::Union, _)
+                | Res::Def(DefKind::Enum, _)
+                | Res::Def(DefKind::Trait, _)
+                | Res::Def(DefKind::TraitAlias, _)
+                | Res::Def(DefKind::TyAlias, _)
+                | Res::Def(DefKind::AssocTy, _)
+                | Res::PrimTy(..)
+                | Res::Def(DefKind::TyParam, _)
+                | Res::SelfTy(..)
+                | Res::Def(DefKind::OpaqueTy, _)
+                | Res::Def(DefKind::ForeignTy, _) => true,
+                _ => false,
+            },
+            PathSource::Trait(AliasPossibility::No) => match res {
+                Res::Def(DefKind::Trait, _) => true,
+                _ => false,
+            },
+            PathSource::Trait(AliasPossibility::Maybe) => match res {
+                Res::Def(DefKind::Trait, _) => true,
+                Res::Def(DefKind::TraitAlias, _) => true,
+                _ => false,
+            },
+            PathSource::Expr(..) => match res {
+                Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
+                | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
+                | Res::Def(DefKind::Const, _)
+                | Res::Def(DefKind::Static, _)
+                | Res::Local(..)
+                | Res::Def(DefKind::Fn, _)
+                | Res::Def(DefKind::Method, _)
+                | Res::Def(DefKind::AssocConst, _)
+                | Res::SelfCtor(..)
+                | Res::Def(DefKind::ConstParam, _) => true,
+                _ => false,
+            },
+            PathSource::Pat => match res {
+                Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
+                Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) |
+                Res::SelfCtor(..) => true,
+                _ => false,
+            },
+            PathSource::TupleStruct => match res {
+                Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..) => true,
+                _ => false,
+            },
+            PathSource::Struct => match res {
+                Res::Def(DefKind::Struct, _)
+                | Res::Def(DefKind::Union, _)
+                | Res::Def(DefKind::Variant, _)
+                | Res::Def(DefKind::TyAlias, _)
+                | Res::Def(DefKind::AssocTy, _)
+                | Res::SelfTy(..) => true,
+                _ => false,
+            },
+            PathSource::TraitItem(ns) => match res {
+                Res::Def(DefKind::AssocConst, _)
+                | Res::Def(DefKind::Method, _) if ns == ValueNS => true,
+                Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
+                _ => false,
+            },
+        }
+    }
+
+    fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
+        __diagnostic_used!(E0404);
+        __diagnostic_used!(E0405);
+        __diagnostic_used!(E0412);
+        __diagnostic_used!(E0422);
+        __diagnostic_used!(E0423);
+        __diagnostic_used!(E0425);
+        __diagnostic_used!(E0531);
+        __diagnostic_used!(E0532);
+        __diagnostic_used!(E0573);
+        __diagnostic_used!(E0574);
+        __diagnostic_used!(E0575);
+        __diagnostic_used!(E0576);
+        match (self, has_unexpected_resolution) {
+            (PathSource::Trait(_), true) => "E0404",
+            (PathSource::Trait(_), false) => "E0405",
+            (PathSource::Type, true) => "E0573",
+            (PathSource::Type, false) => "E0412",
+            (PathSource::Struct, true) => "E0574",
+            (PathSource::Struct, false) => "E0422",
+            (PathSource::Expr(..), true) => "E0423",
+            (PathSource::Expr(..), false) => "E0425",
+            (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
+            (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
+            (PathSource::TraitItem(..), true) => "E0575",
+            (PathSource::TraitItem(..), false) => "E0576",
+        }
+    }
+}
+
 struct LateResolutionVisitor<'a, 'b> {
-    resolver: &'b mut Resolver<'a>,
+    r: &'b mut Resolver<'a>,
 
     /// The module that represents the current item scope.
-    current_module: Module<'a>,
+    parent_scope: ParentScope<'a>,
 
     /// The current set of local scopes for types and values.
     /// FIXME #4948: Reuse ribs to avoid allocation.
@@ -101,19 +330,6 @@ struct LateResolutionVisitor<'a, 'b> {
     current_type_ascription: Vec<Span>,
 }
 
-impl<'a> Deref for LateResolutionVisitor<'a, '_> {
-    type Target = Resolver<'a>;
-    fn deref(&self) -> &Self::Target {
-        self.resolver
-    }
-}
-
-impl<'a> DerefMut for LateResolutionVisitor<'a, '_> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        self.resolver
-    }
-}
-
 /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
 impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
     fn visit_item(&mut self, item: &'tcx Item) {
@@ -143,10 +359,10 @@ 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.record_partial_res(ty.id, PartialRes::new(res));
+                self.r.record_partial_res(ty.id, PartialRes::new(res));
             }
             _ => (),
         }
@@ -233,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
                     }
@@ -250,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 {
@@ -267,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);
@@ -290,10 +506,13 @@ fn visit_generics(&mut self, generics: &'tcx Generics) {
 
 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 graph_root = resolver.graph_root;
+        let parent_scope = ParentScope::module(graph_root);
         LateResolutionVisitor {
-            resolver,
-            current_module: graph_root,
+            r: resolver,
+            parent_scope,
             ribs: PerNS {
                 value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
                 type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
@@ -309,18 +528,14 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
         }
     }
 
-    fn parent_scope(&self) -> ParentScope<'a> {
-        ParentScope { module: self.current_module, ..self.dummy_parent_scope() }
-    }
-
     fn resolve_ident_in_lexical_scope(&mut self,
                                       ident: Ident,
                                       ns: Namespace,
                                       record_used_id: Option<NodeId>,
                                       path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
-        self.resolver.resolve_ident_in_lexical_scope(
-            ident, ns, &self.parent_scope(), record_used_id, path_span, &self.ribs[ns]
+        self.r.resolve_ident_in_lexical_scope(
+            ident, ns, &self.parent_scope, record_used_id, path_span, &self.ribs[ns]
         )
     }
 
@@ -332,8 +547,8 @@ fn resolve_path(
         path_span: Span,
         crate_lint: CrateLint,
     ) -> PathResult<'a> {
-        self.resolver.resolve_path_with_ribs(
-            path, opt_ns, &self.parent_scope(), record_used, path_span, crate_lint, &self.ribs
+        self.r.resolve_path_with_ribs(
+            path, opt_ns, &self.parent_scope, record_used, path_span, crate_lint, Some(&self.ribs)
         )
     }
 
@@ -342,7 +557,7 @@ fn resolve_path(
     // We maintain a list of value ribs and type ribs.
     //
     // Simultaneously, we keep track of the current position in the module
-    // graph in the `current_module` pointer. When we go to resolve a name in
+    // graph in the `parent_scope.module` pointer. When we go to resolve a name in
     // the value or type namespaces, we first look through all the ribs and
     // then query the module graph. When we resolve a name in the module
     // namespace, we can skip all the ribs (since nested modules are not
@@ -358,18 +573,17 @@ fn resolve_path(
     fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
         where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
     {
-        let id = self.definitions.local_def_id(id);
-        let module = self.module_map.get(&id).cloned(); // clones a reference
+        let id = self.r.definitions.local_def_id(id);
+        let module = self.r.module_map.get(&id).cloned(); // clones a reference
         if let Some(module) = module {
             // Move down in the graph.
-            let orig_module = replace(&mut self.current_module, module);
+            let orig_module = replace(&mut self.parent_scope.module, module);
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
-            self.finalize_current_module_macro_resolutions(module);
             let ret = f(self);
 
-            self.current_module = orig_module;
+            self.parent_scope.module = orig_module;
             self.ribs[ValueNS].pop();
             self.ribs[TypeNS].pop();
             ret
@@ -391,7 +605,7 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
                 // If an invocation of this macro created `ident`, give up on `ident`
                 // and switch to `ident`'s source from the macro definition.
                 MacroDefinition(def) => {
-                    if def == self.macro_def(ident.span.ctxt()) {
+                    if def == self.r.macro_def(ident.span.ctxt()) {
                         ident.span.remove_mark();
                     }
                 }
@@ -412,7 +626,7 @@ fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
         debug!("resolve_adt");
         self.with_current_self_item(item, |this| {
             this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
-                let item_def_id = this.definitions.local_def_id(item.id);
+                let item_def_id = this.r.definitions.local_def_id(item.id);
                 this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| {
                     visit::walk_item(this, item);
                 });
@@ -434,7 +648,7 @@ fn future_proof_import(&mut self, use_tree: &UseTree) {
             };
             let report_error = |this: &Self, ns| {
                 let what = if ns == TypeNS { "type parameters" } else { "local variables" };
-                this.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
+                this.r.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
             };
 
             for &ns in nss {
@@ -444,13 +658,13 @@ fn future_proof_import(&mut self, use_tree: &UseTree) {
                     }
                     Some(LexicalScopeBinding::Item(binding)) => {
                         let orig_blacklisted_binding =
-                            replace(&mut self.blacklisted_binding, Some(binding));
+                            replace(&mut self.r.blacklisted_binding, Some(binding));
                         if let Some(LexicalScopeBinding::Res(..)) =
                                 self.resolve_ident_in_lexical_scope(ident, ns, None,
                                                                     use_tree.prefix.span) {
                             report_error(self, ns);
                         }
-                        self.blacklisted_binding = orig_blacklisted_binding;
+                        self.r.blacklisted_binding = orig_blacklisted_binding;
                     }
                     None => {}
                 }
@@ -492,7 +706,7 @@ fn resolve_item(&mut self, item: &Item) {
             ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
-                    let local_def_id = this.definitions.local_def_id(item.id);
+                    let local_def_id = this.r.definitions.local_def_id(item.id);
                     this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_param_bound, bounds);
@@ -537,7 +751,7 @@ fn resolve_item(&mut self, item: &Item) {
             ItemKind::TraitAlias(ref generics, ref bounds) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
-                    let local_def_id = this.definitions.local_def_id(item.id);
+                    let local_def_id = this.r.definitions.local_def_id(item.id);
                     this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_param_bound, bounds);
@@ -597,17 +811,17 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters
                                     ident.name,
                                     *span,
                                 );
-                                resolve_error(self, param.ident.span, err);
+                                self.r.report_error(param.ident.span, err);
                             }
                             seen_bindings.entry(ident).or_insert(param.ident.span);
 
                             // Plain insert (no renaming).
                             let res = Res::Def(
                                 DefKind::TyParam,
-                                self.definitions.local_def_id(param.id),
+                                self.r.definitions.local_def_id(param.id),
                             );
                             function_type_rib.bindings.insert(ident, res);
-                            self.record_partial_res(param.id, PartialRes::new(res));
+                            self.r.record_partial_res(param.id, PartialRes::new(res));
                         }
                         GenericParamKind::Const { .. } => {
                             let ident = param.ident.modern();
@@ -619,16 +833,16 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters
                                     ident.name,
                                     *span,
                                 );
-                                resolve_error(self, param.ident.span, err);
+                                self.r.report_error(param.ident.span, err);
                             }
                             seen_bindings.entry(ident).or_insert(param.ident.span);
 
                             let res = Res::Def(
                                 DefKind::ConstParam,
-                                self.definitions.local_def_id(param.id),
+                                self.r.definitions.local_def_id(param.id),
                             );
                             function_value_rib.bindings.insert(ident, res);
-                            self.record_partial_res(param.id, PartialRes::new(res));
+                            self.r.record_partial_res(param.id, PartialRes::new(res));
                         }
                     }
                 }
@@ -757,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();
@@ -768,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();
@@ -787,7 +1001,7 @@ fn resolve_implementation(&mut self,
             this.with_self_rib(Res::SelfTy(None, None), |this| {
                 // Resolve the trait reference, if necessary.
                 this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
-                    let item_def_id = this.definitions.local_def_id(item_id);
+                    let item_def_id = this.r.definitions.local_def_id(item_id);
                     this.with_self_rib(Res::SelfTy(trait_id, Some(item_def_id)), |this| {
                         if let Some(trait_ref) = opt_trait_reference.as_ref() {
                             // Resolve type arguments in the trait path.
@@ -802,9 +1016,6 @@ fn resolve_implementation(&mut self,
                             this.with_self_struct_ctor_rib(item_def_id, |this| {
                                 debug!("resolve_implementation with_self_struct_ctor_rib");
                                 for impl_item in impl_items {
-                                    this.resolver.resolve_visibility(
-                                        &impl_item.vis, &this.parent_scope()
-                                    );
                                     // We also need a new scope for the impl item type parameters.
                                     let generic_params = HasGenericParams(&impl_item.generics,
                                                                           AssocItemRibKind);
@@ -879,17 +1090,16 @@ fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err:
         // If there is a TraitRef in scope for an impl, then the method must be in the
         // trait.
         if let Some((module, _)) = self.current_trait_ref {
-            let parent_scope = &self.parent_scope();
-            if self.resolve_ident_in_module(
+            if self.r.resolve_ident_in_module(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
-                parent_scope,
+                &self.parent_scope,
                 false,
                 span,
             ).is_err() {
                 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
-                resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
+                self.r.report_error(span, err(ident.name, &path_names_to_string(path)));
             }
         }
     }
@@ -914,7 +1124,7 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
 
         pat.walk(&mut |pat| {
             if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
-                if sub_pat.is_some() || match self.partial_res_map.get(&pat.id)
+                if sub_pat.is_some() || match self.r.partial_res_map.get(&pat.id)
                                                                   .map(|res| res.base_res()) {
                     Some(Res::Local(..)) => true,
                     _ => false,
@@ -932,69 +1142,57 @@ 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 {
-            resolve_error(self,
-                          *v.origin.iter().next().unwrap(),
-                          ResolutionError::VariableNotBoundInPattern(v));
+        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));
         }
+
         let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
         inconsistent_vars.sort();
         for (name, v) in inconsistent_vars {
-            resolve_error(self, v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
+            self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
         }
     }
 
@@ -1018,22 +1216,23 @@ 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) {
         debug!("(resolving block) entering block");
         // Move down in the graph, if there's an anonymous module rooted here.
-        let orig_module = self.current_module;
-        let anonymous_module = self.block_map.get(&block.id).cloned(); // clones a reference
+        let orig_module = self.parent_scope.module;
+        let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
 
         let mut num_macro_definition_ribs = 0;
         if let Some(anonymous_module) = anonymous_module {
             debug!("(resolving block) found anonymous module, moving down");
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
-            self.current_module = anonymous_module;
-            self.finalize_current_module_macro_resolutions(anonymous_module);
+            self.parent_scope.module = anonymous_module;
         } else {
             self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
@@ -1043,7 +1242,7 @@ fn resolve_block(&mut self, block: &Block) {
             if let StmtKind::Item(ref item) = stmt.node {
                 if let ItemKind::MacroDef(..) = item.node {
                     num_macro_definition_ribs += 1;
-                    let res = self.definitions.local_def_id(item.id);
+                    let res = self.r.definitions.local_def_id(item.id);
                     self.ribs[ValueNS].push(Rib::new(MacroDefinition(res)));
                     self.label_ribs.push(Rib::new(MacroDefinition(res)));
                 }
@@ -1053,7 +1252,7 @@ fn resolve_block(&mut self, block: &Block) {
         }
 
         // Move back up.
-        self.current_module = orig_module;
+        self.parent_scope.module = orig_module;
         for _ in 0 .. num_macro_definition_ribs {
             self.ribs[ValueNS].pop();
             self.label_ribs.pop();
@@ -1082,8 +1281,7 @@ fn fresh_binding(&mut self,
         match bindings.get(&ident).cloned() {
             Some(id) if id == outer_pat_id => {
                 // `Variant(a, a)`, error
-                resolve_error(
-                    self,
+                self.r.report_error(
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
                         &ident.as_str())
@@ -1091,8 +1289,7 @@ fn fresh_binding(&mut self,
             }
             Some(..) if pat_src == PatternSource::FnParam => {
                 // `fn f(a: u8, a: u8)`, error
-                resolve_error(
-                    self,
+                self.r.report_error(
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
                         &ident.as_str())
@@ -1145,7 +1342,7 @@ fn resolve_pattern(&mut self,
                             Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
                                 // Disambiguate in favor of a unit struct/variant
                                 // or constant pattern.
-                                self.record_use(ident, ValueNS, binding.unwrap(), false);
+                                self.r.record_use(ident, ValueNS, binding.unwrap(), false);
                                 Some(res)
                             }
                             Res::Def(DefKind::Ctor(..), _)
@@ -1156,8 +1353,7 @@ fn resolve_pattern(&mut self,
                                 // to something unusable as a pattern (e.g., constructor function),
                                 // but we still conservatively report an error, see
                                 // issues/33118#issuecomment-233962221 for one reason why.
-                                resolve_error(
-                                    self,
+                                self.r.report_error(
                                     ident.span,
                                     ResolutionError::BindingShadowsSomethingUnacceptable(
                                         pat_src.descr(), ident.name, binding.unwrap())
@@ -1178,7 +1374,7 @@ fn resolve_pattern(&mut self,
                         self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
                     });
 
-                    self.record_partial_res(pat.id, PartialRes::new(res));
+                    self.r.record_partial_res(pat.id, PartialRes::new(res));
                 }
 
                 PatKind::TupleStruct(ref path, ..) => {
@@ -1234,10 +1430,10 @@ fn smart_resolve_path_fragment(&mut self,
 
         let report_errors = |this: &mut Self, res: Option<Res>| {
             let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
-            let def_id = this.current_module.normal_ancestor_id;
-            let node_id = this.definitions.as_local_node_id(def_id).unwrap();
+            let def_id = this.parent_scope.module.normal_ancestor_id;
+            let node_id = this.r.definitions.as_local_node_id(def_id).unwrap();
             let better = res.is_some();
-            this.use_injections.push(UseError { err, candidates, node_id, better });
+            this.r.use_injections.push(UseError { err, candidates, node_id, better });
             PartialRes::new(Res::Err)
         };
 
@@ -1259,11 +1455,11 @@ fn smart_resolve_path_fragment(&mut self,
                     let mut res = None;
                     if let Res::Def(DefKind::Struct, def_id) = partial_res.base_res() {
                         if let Some((ctor_res, ctor_vis))
-                                = self.struct_constructors.get(&def_id).cloned() {
+                                = self.r.struct_constructors.get(&def_id).cloned() {
                             if is_expected(ctor_res) &&
-                               self.is_accessible_from(ctor_vis, self.current_module) {
+                               self.r.is_accessible_from(ctor_vis, self.parent_scope.module) {
                                 let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
-                                self.session.buffer_lint(lint, id, span,
+                                self.r.session.buffer_lint(lint, id, span,
                                     "private struct constructors are not usable through \
                                      re-exports in outer modules",
                                 );
@@ -1282,12 +1478,12 @@ fn smart_resolve_path_fragment(&mut self,
                 if ns == ValueNS {
                     let item_name = path.last().unwrap().ident;
                     let traits = self.get_traits_containing_item(item_name, ns);
-                    self.trait_map.insert(id, traits);
+                    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.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) {
+                if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) {
                     let cl = CrateLint::No;
                     let ns = Some(ns);
                     if let PathResult::Module(_) | PathResult::NonModule(_) =
@@ -1296,7 +1492,7 @@ fn smart_resolve_path_fragment(&mut self,
                         let item_span = path.iter().last().map(|segment| segment.ident.span)
                             .unwrap_or(span);
                         debug!("accessed item from `std` submodule as a bare type {:?}", std_path);
-                        let mut hm = self.session.confused_type_with_std_module.borrow_mut();
+                        let mut hm = self.r.session.confused_type_with_std_module.borrow_mut();
                         hm.insert(item_span, span);
                         // In some places (E0223) we only have access to the full path
                         hm.insert(span, span);
@@ -1309,14 +1505,14 @@ fn smart_resolve_path_fragment(&mut self,
 
         if let PathSource::TraitItem(..) = source {} else {
             // Avoid recording definition of `A::B` in `<T as A>::B::C`.
-            self.record_partial_res(id, partial_res);
+            self.r.record_partial_res(id, partial_res);
         }
         partial_res
     }
 
     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,
@@ -1360,9 +1556,9 @@ fn resolve_qpath_anywhere(
         if qself.is_none() {
             let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
             let path = Path { segments: path.iter().map(path_seg).collect(), span };
-            let parent_scope = &self.parent_scope();
-            if let Ok((_, res)) =
-                    self.resolve_macro_path(&path, None, parent_scope, false, false) {
+            if let Ok((_, res)) = self.r.resolve_macro_path(
+                &path, None, &self.parent_scope, false, false
+            ) {
                 return Some(PartialRes::new(res));
             }
         }
@@ -1455,15 +1651,15 @@ fn resolve_qpath(
             PathResult::Module(ModuleOrUniformRoot::Module(_)) |
             PathResult::Failed { .. }
                     if (ns == TypeNS || path.len() > 1) &&
-                       self.primitive_type_table.primitive_types
+                       self.r.primitive_type_table.primitive_types
                            .contains_key(&path[0].ident.name) => {
-                let prim = self.primitive_type_table.primitive_types[&path[0].ident.name];
+                let prim = self.r.primitive_type_table.primitive_types[&path[0].ident.name];
                 PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
             }
             PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
                 PartialRes::new(module.res().unwrap()),
             PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
-                resolve_error(self, span, ResolutionError::FailedToResolve { label, suggestion });
+                self.r.report_error(span, ResolutionError::FailedToResolve { label, suggestion });
                 PartialRes::new(Res::Err)
             }
             PathResult::Module(..) | PathResult::Failed { .. } => return None,
@@ -1489,7 +1685,7 @@ fn resolve_qpath(
             };
             if result.base_res() == unqualified_result {
                 let lint = lint::builtin::UNUSED_QUALIFICATIONS;
-                self.session.buffer_lint(lint, id, span, "unnecessary qualification")
+                self.r.session.buffer_lint(lint, id, span, "unnecessary qualification")
             }
         }
 
@@ -1552,15 +1748,15 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                             });
                             find_best_match_for_name(names, &*ident.as_str(), None)
                         });
-                        self.record_partial_res(expr.id, PartialRes::new(Res::Err));
-                        resolve_error(self,
-                                      label.ident.span,
-                                      ResolutionError::UndeclaredLabel(&label.ident.as_str(),
-                                                                       close_match));
+                        self.r.record_partial_res(expr.id, PartialRes::new(Res::Err));
+                        self.r.report_error(
+                            label.ident.span,
+                            ResolutionError::UndeclaredLabel(&label.ident.as_str(), close_match),
+                        );
                     }
                     Some(node_id) => {
                         // Since this res is a label, it is never read.
-                        self.label_res_map.insert(expr.id, node_id);
+                        self.r.label_res_map.insert(expr.id, node_id);
                         self.unused_labels.remove(&node_id);
                     }
                 }
@@ -1672,13 +1868,13 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
                 let traits = self.get_traits_containing_item(ident, ValueNS);
-                self.trait_map.insert(expr.id, traits);
+                self.r.trait_map.insert(expr.id, traits);
             }
             ExprKind::MethodCall(ref segment, ..) => {
                 debug!("(recording candidate traits for expr) recording traits for {}",
                        expr.id);
                 let traits = self.get_traits_containing_item(segment.ident, ValueNS);
-                self.trait_map.insert(expr.id, traits);
+                self.r.trait_map.insert(expr.id, traits);
             }
             _ => {
                 // Nothing to do.
@@ -1693,12 +1889,11 @@ fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace)
         let mut found_traits = Vec::new();
         // Look for the current trait.
         if let Some((module, _)) = self.current_trait_ref {
-            let parent_scope = &self.parent_scope();
-            if self.resolve_ident_in_module(
+            if self.r.resolve_ident_in_module(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
-                parent_scope,
+                &self.parent_scope,
                 false,
                 module.span,
             ).is_ok() {
@@ -1708,15 +1903,15 @@ fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace)
         }
 
         ident.span = ident.span.modern();
-        let mut search_module = self.current_module;
+        let mut search_module = self.parent_scope.module;
         loop {
             self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
             search_module = unwrap_or!(
-                self.hygienic_lexical_parent(search_module, &mut ident.span), break
+                self.r.hygienic_lexical_parent(search_module, &mut ident.span), break
             );
         }
 
-        if let Some(prelude) = self.prelude {
+        if let Some(prelude) = self.r.prelude {
             if !search_module.no_implicit_prelude {
                 self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits);
             }
@@ -1734,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, _) |
@@ -1755,12 +1950,11 @@ fn get_traits_in_module_containing_item(&mut self,
                 ).is_none() {
                     continue
                 }
-                let parent_scope = &self.parent_scope();
-                if self.resolve_ident_in_module_unadjusted(
+                if self.r.resolve_ident_in_module_unadjusted(
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     ns,
-                    parent_scope,
+                    &self.parent_scope,
                     false,
                     module.span,
                 ).is_ok() {
@@ -1784,8 +1978,8 @@ fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>,
                                trait_name: Ident) -> SmallVec<[NodeId; 1]> {
         let mut import_ids = smallvec![];
         while let NameBindingKind::Import { directive, binding, .. } = kind {
-            self.maybe_unused_trait_imports.insert(directive.id);
-            self.add_to_glob_map(&directive, trait_name);
+            self.r.maybe_unused_trait_imports.insert(directive.id);
+            self.r.add_to_glob_map(&directive, trait_name);
             import_ids.push(directive.id);
             kind = &binding.kind;
         };
@@ -1796,8 +1990,6 @@ fn find_transitive_imports(&mut self, mut kind: &NameBindingKind<'_>,
 impl<'a> Resolver<'a> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
-        let module = late_resolution_visitor.current_module;
-        late_resolution_visitor.finalize_current_module_macro_resolutions(module);
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.unused_labels.iter() {
             self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");