about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-08 23:57:35 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-10 13:16:06 +0300
commitf360d795f1ac31ed0e4e2f3225f9122db73e1b92 (patch)
treece0d56d9282fd82c30e15af6201ad26cfe0d3189
parent9c86ce76e51439a39765343f2f9ac03e12f04898 (diff)
downloadrust-f360d795f1ac31ed0e4e2f3225f9122db73e1b92.tar.gz
rust-f360d795f1ac31ed0e4e2f3225f9122db73e1b92.zip
resolve: Move some more code around
Move methods logically belonging to build-reduced-graph into `impl BuildReducedGraphVisitor` and `build_reduced_graph.rs`
Move types mostly specific to late resolution closer to the late resolution visitor
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs507
-rw-r--r--src/librustc_resolve/late.rs233
-rw-r--r--src/librustc_resolve/late/diagnostics.rs4
-rw-r--r--src/librustc_resolve/lib.rs335
-rw-r--r--src/librustc_resolve/macros.rs80
-rw-r--r--src/librustc_resolve/resolve_imports.rs59
6 files changed, 602 insertions, 616 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a6fbb0babbe..6e5750e752e 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -3,13 +3,13 @@
 //! Here we build the "reduced graph": the graph of the module tree without
 //! any imports resolved.
 
-use crate::macros::{InvocationData, LegacyScope};
+use crate::macros::{InvocationData, LegacyBinding, LegacyScope};
 use crate::resolve_imports::ImportDirective;
 use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
 use crate::{ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
 use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
-use crate::{ResolutionError, Determinacy};
+use crate::{ResolutionError, Determinacy, PathResult, CrateLint};
 
 use rustc::bug;
 use rustc::hir::def::{self, *};
@@ -29,11 +29,11 @@ use syntax::attr;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
-use syntax::ext::base::SyntaxExtension;
+use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::hygiene::ExpnId;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
-use syntax::span_err;
+use syntax::{span_err, struct_span_err};
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
@@ -93,14 +93,195 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
+        if def_id.krate == LOCAL_CRATE {
+            return self.module_map[&def_id]
+        }
+
+        let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
+        if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
+            return module;
+        }
+
+        let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
+            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
+        } else {
+            let def_key = self.cstore.def_key(def_id);
+            (def_key.disambiguated_data.data.get_opt_name().unwrap(),
+             Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
+        };
+
+        let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol());
+        let module = self.arenas.alloc_module(ModuleData::new(
+            parent, kind, def_id, ExpnId::root(), DUMMY_SP
+        ));
+        self.extern_module_map.insert((def_id, macros_only), module);
+        module
+    }
+
+    pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
+        let def_id = match self.macro_defs.get(&expn_id) {
+            Some(def_id) => *def_id,
+            None => return self.graph_root,
+        };
+        if let Some(id) = self.definitions.as_local_node_id(def_id) {
+            self.local_macro_def_scopes[&id]
+        } else if self.is_builtin_macro(Some(def_id)) {
+            self.injected_crate.unwrap_or(self.graph_root)
+        } else {
+            let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
+            self.get_module(module_def_id)
+        }
+    }
+
+    crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
+        match res {
+            Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
+            Res::NonMacroAttr(attr_kind) =>
+                Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
+            _ => None,
+        }
+    }
+
+    crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
+        if let Some(ext) = self.macro_map.get(&def_id) {
+            return Some(ext.clone());
+        }
+
+        let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
+            LoadedMacro::MacroDef(macro_def) => macro_def,
+            LoadedMacro::ProcMacro(ext) => return Some(ext),
+        };
+
+        let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
+        self.macro_map.insert(def_id, ext.clone());
+        Some(ext)
+    }
+
+    /// Ensures that the reduced graph rooted at the given external module
+    /// is built, building it if it is not.
+    pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
+        if module.populated.get() { return }
+        let def_id = module.def_id().unwrap();
+        for child in self.cstore.item_children_untracked(def_id, self.session) {
+            let child = child.map_id(|_| panic!("unexpected id"));
+            BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self }
+                .build_reduced_graph_for_external_crate_res(module, child);
+        }
+        module.populated.set(true)
+    }
+}
+
+pub struct BuildReducedGraphVisitor<'a, 'b> {
+    pub r: &'b mut Resolver<'a>,
+    pub parent_scope: ParentScope<'a>,
+}
+
+impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
+    fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
+        let parent_scope = &self.parent_scope;
+        match vis.node {
+            ast::VisibilityKind::Public => ty::Visibility::Public,
+            ast::VisibilityKind::Crate(..) => {
+                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+            }
+            ast::VisibilityKind::Inherited => {
+                ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id)
+            }
+            ast::VisibilityKind::Restricted { ref path, id, .. } => {
+                // For visibilities we are not ready to provide correct implementation of "uniform
+                // paths" right now, so on 2018 edition we only allow module-relative paths for now.
+                // On 2015 edition visibilities are resolved as crate-relative by default,
+                // so we are prepending a root segment if necessary.
+                let ident = path.segments.get(0).expect("empty path in visibility").ident;
+                let crate_root = if ident.is_path_segment_keyword() {
+                    None
+                } else if ident.span.rust_2018() {
+                    let msg = "relative paths are not supported in visibilities on 2018 edition";
+                    self.r.session.struct_span_err(ident.span, msg)
+                        .span_suggestion(
+                            path.span,
+                            "try",
+                            format!("crate::{}", path),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    return ty::Visibility::Public;
+                } else {
+                    let ctxt = ident.span.ctxt();
+                    Some(Segment::from_ident(Ident::new(
+                        kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
+                    )))
+                };
+
+                let segments = crate_root.into_iter()
+                    .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
+                let expected_found_error = |this: &Self, res: Res| {
+                    let path_str = Segment::names_to_string(&segments);
+                    struct_span_err!(this.r.session, path.span, E0577,
+                                     "expected module, found {} `{}`", res.descr(), path_str)
+                        .span_label(path.span, "not a module").emit();
+                };
+                match self.r.resolve_path(
+                    &segments,
+                    Some(TypeNS),
+                    parent_scope,
+                    true,
+                    path.span,
+                    CrateLint::SimplePath(id),
+                ) {
+                    PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
+                        let res = module.res().expect("visibility resolved to unnamed block");
+                        self.r.record_partial_res(id, PartialRes::new(res));
+                        if module.is_normal() {
+                            if res == Res::Err {
+                                ty::Visibility::Public
+                            } else {
+                                let vis = ty::Visibility::Restricted(res.def_id());
+                                if self.r.is_accessible_from(vis, parent_scope.module) {
+                                    vis
+                                } else {
+                                    let msg =
+                                        "visibilities can only be restricted to ancestor modules";
+                                    self.r.session.span_err(path.span, msg);
+                                    ty::Visibility::Public
+                                }
+                            }
+                        } else {
+                            expected_found_error(self, res);
+                            ty::Visibility::Public
+                        }
+                    }
+                    PathResult::Module(..) => {
+                        self.r.session.span_err(path.span, "visibility must resolve to a module");
+                        ty::Visibility::Public
+                    }
+                    PathResult::NonModule(partial_res) => {
+                        expected_found_error(self, partial_res.base_res());
+                        ty::Visibility::Public
+                    }
+                    PathResult::Failed { span, label, suggestion, .. } => {
+                        self.r.report_error(
+                            span, ResolutionError::FailedToResolve { label, suggestion }
+                        );
+                        ty::Visibility::Public
+                    }
+                    PathResult::Indeterminate => {
+                        span_err!(self.r.session, path.span, E0578,
+                                  "cannot determine resolution for the visibility");
+                        ty::Visibility::Public
+                    }
+                }
+            }
+        }
+    }
+
     fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
         if !field_names.is_empty() {
-            self.field_names.insert(def_id, field_names);
+            self.r.field_names.insert(def_id, field_names);
         }
     }
-}
 
-impl<'a> BuildReducedGraphVisitor<'_, 'a> {
     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
         // If any statements are items, we need to create an anonymous module
         block.stmts.iter().any(|statement| match statement.node {
@@ -109,6 +290,54 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
         })
     }
 
+    // Add an import directive to the current module.
+    fn add_import_directive(
+        &mut self,
+        module_path: Vec<Segment>,
+        subclass: ImportDirectiveSubclass<'a>,
+        span: Span,
+        id: NodeId,
+        item: &ast::Item,
+        root_span: Span,
+        root_id: NodeId,
+        vis: ty::Visibility,
+    ) {
+        let parent_scope = &self.parent_scope;
+        let current_module = parent_scope.module;
+        let directive = self.r.arenas.alloc_import_directive(ImportDirective {
+            parent_scope: parent_scope.clone(),
+            module_path,
+            imported_module: Cell::new(None),
+            subclass,
+            span,
+            id,
+            use_span: item.span,
+            use_span_with_attributes: item.span_with_attributes(),
+            has_attributes: !item.attrs.is_empty(),
+            root_span,
+            root_id,
+            vis: Cell::new(vis),
+            used: Cell::new(false),
+        });
+
+        debug!("add_import_directive({:?})", directive);
+
+        self.r.indeterminate_imports.push(directive);
+        match directive.subclass {
+            SingleImport { target, type_ns_only, .. } => {
+                self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
+                    let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
+                    resolution.add_single_import(directive);
+                });
+            }
+            // We don't add prelude imports to the globs since they only affect lexical scopes,
+            // which are not relevant to import resolution.
+            GlobImport { is_prelude: true, .. } => {}
+            GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
+            _ => unreachable!(),
+        }
+    }
+
     fn build_reduced_graph_for_use_tree(
         &mut self,
         // This particular use tree
@@ -117,7 +346,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
         parent_prefix: &[Segment],
         nested: bool,
         // The whole `use` item
-        parent_scope: &ParentScope<'a>,
         item: &Item,
         vis: ty::Visibility,
         root_span: Span,
@@ -250,7 +478,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                     root_span,
                     item.id,
                     vis,
-                    parent_scope.clone(),
                 );
             }
             ast::UseTreeKind::Glob => {
@@ -267,7 +494,6 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                     root_span,
                     item.id,
                     vis,
-                    parent_scope.clone(),
                 );
             }
             ast::UseTreeKind::Nested(ref items) => {
@@ -298,7 +524,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                         // This particular use tree
                         tree, id, &prefix, true,
                         // The whole `use` item
-                        parent_scope, item, vis, root_span,
+                        item, vis, root_span,
                     );
                 }
 
@@ -322,7 +548,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                         // This particular use tree
                         &tree, id, &prefix, true,
                         // The whole `use` item
-                        parent_scope, item, ty::Visibility::Invisible, root_span,
+                        item, ty::Visibility::Invisible, root_span,
                     );
                 }
             }
@@ -331,12 +557,12 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
 
     /// Constructs the reduced graph for one item.
     fn build_reduced_graph_for_item(&mut self, item: &Item) {
-        let parent_scope = &self.parent_scope.clone();
+        let parent_scope = &self.parent_scope;
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
         let ident = item.ident.gensym_if_underscore();
         let sp = item.span;
-        let vis = self.r.resolve_visibility(&item.vis, parent_scope);
+        let vis = self.resolve_visibility(&item.vis);
 
         match item.node {
             ItemKind::Use(ref use_tree) => {
@@ -344,7 +570,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                     // This particular use tree
                     use_tree, item.id, &[], false,
                     // The whole `use` item
-                    parent_scope, item, vis, use_tree.span,
+                    item, vis, use_tree.span,
                 );
             }
 
@@ -376,13 +602,13 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                     }
                 }
 
-                let used = self.process_legacy_macro_imports(item, module, parent_scope);
+                let used = self.process_legacy_macro_imports(item, module);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
                 let directive = self.r.arenas.alloc_import_directive(ImportDirective {
                     root_id: item.id,
                     id: item.id,
-                    parent_scope: parent_scope.clone(),
+                    parent_scope: self.parent_scope.clone(),
                     imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
                     subclass: ImportDirectiveSubclass::ExternCrate {
                         source: orig_name,
@@ -459,7 +685,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
-                self.r.define_macro(item, parent_scope);
+                self.define_macro(item);
             }
 
             // These items live in the type namespace.
@@ -515,14 +741,14 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
 
                 // Record field names for error reporting.
                 let field_names = struct_def.fields().iter().filter_map(|field| {
-                    let field_vis = self.r.resolve_visibility(&field.vis, parent_scope);
+                    let field_vis = self.resolve_visibility(&field.vis);
                     if ctor_vis.is_at_least(field_vis, &*self.r) {
                         ctor_vis = field_vis;
                     }
                     field.ident.map(|ident| ident.name)
                 }).collect();
                 let item_def_id = self.r.definitions.local_def_id(item.id);
-                self.r.insert_field_names(item_def_id, field_names);
+                self.insert_field_names(item_def_id, field_names);
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
@@ -542,14 +768,18 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
 
                 // Record field names for error reporting.
                 let field_names = vdata.fields().iter().filter_map(|field| {
-                    self.r.resolve_visibility(&field.vis, parent_scope);
+                    self.resolve_visibility(&field.vis);
                     field.ident.map(|ident| ident.name)
                 }).collect();
                 let item_def_id = self.r.definitions.local_def_id(item.id);
-                self.r.insert_field_names(item_def_id, field_names);
+                self.insert_field_names(item_def_id, field_names);
             }
 
-            ItemKind::Impl(..) => {}
+            ItemKind::Impl(.., ref impl_items) => {
+                for impl_item in impl_items {
+                    self.resolve_visibility(&impl_item.vis);
+                }
+            }
 
             ItemKind::Trait(..) => {
                 let def_id = self.r.definitions.local_def_id(item.id);
@@ -619,7 +849,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
         };
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
-        let vis = self.r.resolve_visibility(&item.vis, &self.parent_scope);
+        let vis = self.resolve_visibility(&item.vis);
         self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
     }
 
@@ -636,9 +866,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
             self.parent_scope.module = module; // Descend into the block.
         }
     }
-}
 
-impl<'a> Resolver<'a> {
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_res(
         &mut self,
@@ -654,12 +882,12 @@ impl<'a> Resolver<'a> {
         match res {
             Res::Def(kind @ DefKind::Mod, def_id)
             | Res::Def(kind @ DefKind::Enum, def_id) => {
-                let module = self.new_module(parent,
+                let module = self.r.new_module(parent,
                                              ModuleKind::Def(kind, def_id, ident.name),
                                              def_id,
                                              expansion,
                                              span);
-                self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
             }
             Res::Def(DefKind::Variant, _)
             | Res::Def(DefKind::TyAlias, _)
@@ -668,140 +896,61 @@ impl<'a> Resolver<'a> {
             | Res::Def(DefKind::TraitAlias, _)
             | Res::PrimTy(..)
             | Res::ToolMod => {
-                self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
             }
             Res::Def(DefKind::Fn, _)
             | Res::Def(DefKind::Static, _)
             | Res::Def(DefKind::Const, _)
             | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
-                self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
             }
             Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
-                self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
 
                 if let Some(struct_def_id) =
-                        self.cstore.def_key(def_id).parent
+                        self.r.cstore.def_key(def_id).parent
                             .map(|index| DefId { krate: def_id.krate, index: index }) {
-                    self.struct_constructors.insert(struct_def_id, (res, vis));
+                    self.r.struct_constructors.insert(struct_def_id, (res, vis));
                 }
             }
             Res::Def(DefKind::Trait, def_id) => {
                 let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
-                let module = self.new_module(parent,
+                let module = self.r.new_module(parent,
                                              module_kind,
                                              parent.normal_ancestor_id,
                                              expansion,
                                              span);
-                self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
 
-                for child in self.cstore.item_children_untracked(def_id, self.session) {
+                for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
                     let res = child.res.map_id(|_| panic!("unexpected id"));
                     let ns = if let Res::Def(DefKind::AssocTy, _) = res {
                         TypeNS
                     } else { ValueNS };
-                    self.define(module, child.ident, ns,
+                    self.r.define(module, child.ident, ns,
                                 (res, ty::Visibility::Public, DUMMY_SP, expansion));
 
-                    if self.cstore.associated_item_cloned_untracked(child.res.def_id())
+                    if self.r.cstore.associated_item_cloned_untracked(child.res.def_id())
                            .method_has_self_argument {
-                        self.has_self.insert(res.def_id());
+                        self.r.has_self.insert(res.def_id());
                     }
                 }
                 module.populated.set(true);
             }
             Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
-                self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
 
                 // Record field names for error reporting.
-                let field_names = self.cstore.struct_field_names_untracked(def_id);
+                let field_names = self.r.cstore.struct_field_names_untracked(def_id);
                 self.insert_field_names(def_id, field_names);
             }
             Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
-                self.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
+                self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
             }
             _ => bug!("unexpected resolution: {:?}", res)
         }
     }
 
-    pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
-        if def_id.krate == LOCAL_CRATE {
-            return self.module_map[&def_id]
-        }
-
-        let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
-        if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
-            return module;
-        }
-
-        let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
-        } else {
-            let def_key = self.cstore.def_key(def_id);
-            (def_key.disambiguated_data.data.get_opt_name().unwrap(),
-             Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
-        };
-
-        let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol());
-        let module = self.arenas.alloc_module(ModuleData::new(
-            parent, kind, def_id, ExpnId::root(), DUMMY_SP
-        ));
-        self.extern_module_map.insert((def_id, macros_only), module);
-        module
-    }
-
-    pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
-        let def_id = match self.macro_defs.get(&expn_id) {
-            Some(def_id) => *def_id,
-            None => return self.graph_root,
-        };
-        if let Some(id) = self.definitions.as_local_node_id(def_id) {
-            self.local_macro_def_scopes[&id]
-        } else if self.is_builtin_macro(Some(def_id)) {
-            self.injected_crate.unwrap_or(self.graph_root)
-        } else {
-            let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
-            self.get_module(module_def_id)
-        }
-    }
-
-    crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
-        match res {
-            Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
-            Res::NonMacroAttr(attr_kind) =>
-                Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
-            _ => None,
-        }
-    }
-
-    crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
-        if let Some(ext) = self.macro_map.get(&def_id) {
-            return Some(ext.clone());
-        }
-
-        let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
-            LoadedMacro::MacroDef(macro_def) => macro_def,
-            LoadedMacro::ProcMacro(ext) => return Some(ext),
-        };
-
-        let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
-        self.macro_map.insert(def_id, ext.clone());
-        Some(ext)
-    }
-
-    /// Ensures that the reduced graph rooted at the given external module
-    /// is built, building it if it is not.
-    pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
-        if module.populated.get() { return }
-        let def_id = module.def_id().unwrap();
-        for child in self.cstore.item_children_untracked(def_id, self.session) {
-            let child = child.map_id(|_| panic!("unexpected id"));
-            self.build_reduced_graph_for_external_crate_res(module, child);
-        }
-        module.populated.set(true)
-    }
-}
-
-impl<'a> BuildReducedGraphVisitor<'_, 'a> {
     fn legacy_import_macro(&mut self,
                            name: Name,
                            binding: &'a NameBinding<'a>,
@@ -816,8 +965,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
     }
 
     /// Returns `true` if we should consider the underlying `extern crate` to be used.
-    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
-                                    parent_scope: &ParentScope<'a>) -> bool {
+    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
         let mut import_all = None;
         let mut single_imports = Vec::new();
         for attr in &item.attrs {
@@ -852,11 +1000,11 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
             }
         }
 
-        let arenas = self.r.arenas;
-        let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
+        let macro_use_directive =
+                |this: &Self, span| this.r.arenas.alloc_import_directive(ImportDirective {
             root_id: item.id,
             id: item.id,
-            parent_scope: parent_scope.clone(),
+            parent_scope: this.parent_scope.clone(),
             imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
             subclass: ImportDirectiveSubclass::MacroUse,
             use_span_with_attributes: item.span_with_attributes(),
@@ -869,9 +1017,9 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
             used: Cell::new(false),
         });
 
-        let allow_shadowing = parent_scope.expansion == ExpnId::root();
+        let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
         if let Some(span) = import_all {
-            let directive = macro_use_directive(span);
+            let directive = macro_use_directive(self, span);
             self.r.potentially_unused_imports.push(directive);
             module.for_each_child(|ident, ns, binding| if ns == MacroNS {
                 let imported_binding = self.r.import(binding, directive);
@@ -883,12 +1031,12 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     MacroNS,
-                    parent_scope,
+                    &self.parent_scope,
                     false,
                     ident.span,
                 );
                 if let Ok(binding) = result {
-                    let directive = macro_use_directive(ident.span);
+                    let directive = macro_use_directive(self, ident.span);
                     self.r.potentially_unused_imports.push(directive);
                     let imported_binding = self.r.import(binding, directive);
                     self.legacy_import_macro(ident.name, imported_binding,
@@ -924,15 +1072,8 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
 
         false
     }
-}
 
-pub struct BuildReducedGraphVisitor<'a, 'b> {
-    pub r: &'a mut Resolver<'b>,
-    pub parent_scope: ParentScope<'b>,
-}
-
-impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
-    fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
+    fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> {
         let invoc_id = id.placeholder_to_expn_id();
 
         self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id);
@@ -947,11 +1088,83 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
 
         invocation_data
     }
+
+    fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
+        if attr::contains_name(&item.attrs, sym::proc_macro) {
+            return Some((MacroKind::Bang, item.ident, item.span));
+        } else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
+            return Some((MacroKind::Attr, item.ident, item.span));
+        } else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
+            if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
+                if let Some(ident) = nested_meta.ident() {
+                    return Some((MacroKind::Derive, ident, ident.span));
+                }
+            }
+        }
+        None
+    }
+
+    fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
+        let parent_scope = &self.parent_scope;
+        let expansion = parent_scope.expansion;
+        let (ext, ident, span, is_legacy) = match &item.node {
+            ItemKind::MacroDef(def) => {
+                let ext = self.r.compile_macro(item, self.r.session.edition());
+                (ext, item.ident, item.span, def.legacy)
+            }
+            ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
+                Some((macro_kind, ident, span)) => {
+                    self.r.proc_macro_stubs.insert(item.id);
+                    (self.r.dummy_ext(macro_kind), ident, span, false)
+                }
+                None => return parent_scope.legacy,
+            }
+            _ => unreachable!(),
+        };
+
+        let def_id = self.r.definitions.local_def_id(item.id);
+        let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
+        self.r.macro_map.insert(def_id, ext);
+        self.r.local_macro_def_scopes.insert(item.id, parent_scope.module);
+
+        if is_legacy {
+            let ident = ident.modern();
+            self.r.macro_names.insert(ident);
+            let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
+            let vis = if is_macro_export {
+                ty::Visibility::Public
+            } else {
+                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+            };
+            let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
+            self.r.set_binding_parent_module(binding, parent_scope.module);
+            self.r.all_macros.insert(ident.name, res);
+            if is_macro_export {
+                let module = self.r.graph_root;
+                self.r.define(module, ident, MacroNS,
+                            (res, vis, span, expansion, IsMacroExport));
+            } else {
+                self.r.check_reserved_macro_name(ident, res);
+                self.r.unused_macros.insert(item.id, span);
+            }
+            LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding {
+                parent_legacy_scope: parent_scope.legacy, binding, ident
+            }))
+        } else {
+            let module = parent_scope.module;
+            let vis = self.resolve_visibility(&item.vis);
+            if vis != ty::Visibility::Public {
+                self.r.unused_macros.insert(item.id, span);
+            }
+            self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
+            self.parent_scope.legacy
+        }
+    }
 }
 
 macro_rules! method {
     ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
-        fn $visit(&mut self, node: &'a $ty) {
+        fn $visit(&mut self, node: &'b $ty) {
             if let $invoc(..) = node.node {
                 self.visit_invoc(node.id);
             } else {
@@ -961,16 +1174,16 @@ macro_rules! method {
     }
 }
 
-impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
     method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
     method!(visit_expr:      ast::Expr,     ast::ExprKind::Mac,       walk_expr);
     method!(visit_pat:       ast::Pat,      ast::PatKind::Mac,        walk_pat);
     method!(visit_ty:        ast::Ty,       ast::TyKind::Mac,         walk_ty);
 
-    fn visit_item(&mut self, item: &'a Item) {
+    fn visit_item(&mut self, item: &'b Item) {
         let macro_use = match item.node {
             ItemKind::MacroDef(..) => {
-                self.parent_scope.legacy = self.r.define_macro(item, &self.parent_scope);
+                self.parent_scope.legacy = self.define_macro(item);
                 return
             }
             ItemKind::Mac(..) => {
@@ -991,7 +1204,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
+    fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
         if let ast::StmtKind::Mac(..) = stmt.node {
             self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id));
         } else {
@@ -999,7 +1212,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
+    fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
         if let ForeignItemKind::Macro(_) = foreign_item.node {
             self.visit_invoc(foreign_item.id);
             return;
@@ -1009,7 +1222,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         visit::walk_foreign_item(self, foreign_item);
     }
 
-    fn visit_block(&mut self, block: &'a Block) {
+    fn visit_block(&mut self, block: &'b Block) {
         let orig_current_module = self.parent_scope.module;
         let orig_current_legacy_scope = self.parent_scope.legacy;
         self.build_reduced_graph_for_block(block);
@@ -1018,7 +1231,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         self.parent_scope.legacy = orig_current_legacy_scope;
     }
 
-    fn visit_trait_item(&mut self, item: &'a TraitItem) {
+    fn visit_trait_item(&mut self, item: &'b TraitItem) {
         let parent = self.parent_scope.module;
 
         if let TraitItemKind::Macro(_) = item.node {
@@ -1059,7 +1272,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
+    fn visit_attribute(&mut self, attr: &'b ast::Attribute) {
         if !attr.is_sugared_doc && is_builtin_attr(attr) {
             self.parent_scope.module.builtin_attrs.borrow_mut().push((
                 attr.path.segments[0].ident, self.parent_scope.clone()
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 0f68e0c054a..239042505d0 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1,9 +1,9 @@
 use GenericParameters::*;
+use RibKind::*;
 
-use crate::{path_names_to_string, AliasPossibility, BindingError, CrateLint, LexicalScopeBinding};
+use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
-use crate::{PathSource, ResolutionError, Resolver, Rib, RibKind, Segment, UseError};
-use crate::RibKind::*;
+use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use log::debug;
 use rustc::{bug, lint, span_bug};
@@ -66,6 +66,230 @@ impl PatternSource {
     }
 }
 
+/// 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> {
     r: &'b mut Resolver<'a>,
 
@@ -786,9 +1010,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                             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.r.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);
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 9c9eb017aef..35cf720ad87 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -1,9 +1,9 @@
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{PathResult, PathSource, RibKind, Segment};
+use crate::{PathResult, PathSource, Segment};
 use crate::path_names_to_string;
 use crate::diagnostics::{add_typo_suggestion, add_module_candidates};
 use crate::diagnostics::{ImportSuggestion, TypoSuggestion};
-use crate::late::LateResolutionVisitor;
+use crate::late::{LateResolutionVisitor, RibKind};
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a2b1873c4f2..83dc40c097b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
@@ -13,22 +11,19 @@
 pub use rustc::hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
-use RibKind::*;
 
 use rustc::hir::map::Definitions;
 use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
-use rustc::hir::def::{
-    self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap
-};
+use rustc::hir::def::{self, DefKind, PartialRes, CtorOf, NonMacroAttrKind, ExportMap};
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::{TraitMap, GlobMap};
 use rustc::ty;
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
-use rustc::{bug, span_bug};
+use rustc::span_bug;
 
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::CStore;
@@ -40,7 +35,7 @@ use syntax::symbol::{Symbol, kw, sym};
 
 use syntax::visit::{self, Visitor};
 use syntax::attr;
-use syntax::ast::{CRATE_NODE_ID, Crate, Expr, ExprKind};
+use syntax::ast::{CRATE_NODE_ID, Crate};
 use syntax::ast::{ItemKind, Path};
 use syntax::{span_err, struct_span_err, unwrap_or};
 
@@ -57,6 +52,7 @@ use rustc_data_structures::sync::Lrc;
 
 use diagnostics::{Suggestion, ImportSuggestion};
 use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
+use late::{PathSource, Rib, RibKind::*};
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
 use macros::{InvocationData, LegacyBinding, LegacyScope};
 
@@ -199,165 +195,6 @@ enum ResolutionError<'a> {
     ConstParamDependentOnTypeParam,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum AliasPossibility {
-    No,
-    Maybe,
-}
-
-#[derive(Copy, Clone, Debug)]
-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",
-            },
-        }
-    }
-
-    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",
-        }
-    }
-}
-
 // A minimal representation of a path segment. We use this in resolve because
 // we synthesize 'path segments' which don't have the rest of an AST or HIR
 // `PathSegment`.
@@ -463,71 +300,6 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
     }
 }
 
-/// The rib kind restricts certain accesses,
-/// e.g. to a `Res::Local` of an outer item.
-#[derive(Copy, Clone, Debug)]
-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)]
-struct Rib<'a, R = Res> {
-    bindings: FxHashMap<Ident, R>,
-    kind: RibKind<'a>,
-}
-
-impl<'a, R> Rib<'a, R> {
-    fn new(kind: RibKind<'a>) -> Rib<'a, R> {
-        Rib {
-            bindings: Default::default(),
-            kind,
-        }
-    }
-}
-
 /// An intermediate resolution result.
 ///
 /// This refers to the thing referred by a name. The difference between `Res` and `Item` is that
@@ -2405,105 +2177,6 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn resolve_visibility(
-        &mut self, vis: &ast::Visibility, parent_scope: &ParentScope<'a>
-    ) -> ty::Visibility {
-        match vis.node {
-            ast::VisibilityKind::Public => ty::Visibility::Public,
-            ast::VisibilityKind::Crate(..) => {
-                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
-            }
-            ast::VisibilityKind::Inherited => {
-                ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id)
-            }
-            ast::VisibilityKind::Restricted { ref path, id, .. } => {
-                // For visibilities we are not ready to provide correct implementation of "uniform
-                // paths" right now, so on 2018 edition we only allow module-relative paths for now.
-                // On 2015 edition visibilities are resolved as crate-relative by default,
-                // so we are prepending a root segment if necessary.
-                let ident = path.segments.get(0).expect("empty path in visibility").ident;
-                let crate_root = if ident.is_path_segment_keyword() {
-                    None
-                } else if ident.span.rust_2018() {
-                    let msg = "relative paths are not supported in visibilities on 2018 edition";
-                    self.session.struct_span_err(ident.span, msg)
-                        .span_suggestion(
-                            path.span,
-                            "try",
-                            format!("crate::{}", path),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    return ty::Visibility::Public;
-                } else {
-                    let ctxt = ident.span.ctxt();
-                    Some(Segment::from_ident(Ident::new(
-                        kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
-                    )))
-                };
-
-                let segments = crate_root.into_iter()
-                    .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
-                let expected_found_error = |this: &Self, res: Res| {
-                    let path_str = Segment::names_to_string(&segments);
-                    struct_span_err!(this.session, path.span, E0577,
-                                     "expected module, found {} `{}`", res.descr(), path_str)
-                        .span_label(path.span, "not a module").emit();
-                };
-                match self.resolve_path(
-                    &segments,
-                    Some(TypeNS),
-                    parent_scope,
-                    true,
-                    path.span,
-                    CrateLint::SimplePath(id),
-                ) {
-                    PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
-                        let res = module.res().expect("visibility resolved to unnamed block");
-                        self.record_partial_res(id, PartialRes::new(res));
-                        if module.is_normal() {
-                            if res == Res::Err {
-                                ty::Visibility::Public
-                            } else {
-                                let vis = ty::Visibility::Restricted(res.def_id());
-                                if self.is_accessible_from(vis, parent_scope.module) {
-                                    vis
-                                } else {
-                                    let msg =
-                                        "visibilities can only be restricted to ancestor modules";
-                                    self.session.span_err(path.span, msg);
-                                    ty::Visibility::Public
-                                }
-                            }
-                        } else {
-                            expected_found_error(self, res);
-                            ty::Visibility::Public
-                        }
-                    }
-                    PathResult::Module(..) => {
-                        self.session.span_err(path.span, "visibility must resolve to a module");
-                        ty::Visibility::Public
-                    }
-                    PathResult::NonModule(partial_res) => {
-                        expected_found_error(self, partial_res.base_res());
-                        ty::Visibility::Public
-                    }
-                    PathResult::Failed { span, label, suggestion, .. } => {
-                        self.report_error(
-                            span, ResolutionError::FailedToResolve { label, suggestion }
-                        );
-                        ty::Visibility::Public
-                    }
-                    PathResult::Indeterminate => {
-                        span_err!(self.session, path.span, E0578,
-                                  "cannot determine resolution for the visibility");
-                        ty::Visibility::Public
-                    }
-                }
-            }
-        }
-    }
-
     fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
         vis.is_accessible_from(module.normal_ancestor_id, self)
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 78edb685edd..1b6599e20e9 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -3,15 +3,14 @@ use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope,
 use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
 use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
 use crate::Namespace::*;
-use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
+use crate::build_reduced_graph::BuildReducedGraphVisitor;
 use crate::resolve_imports::ImportResolver;
-use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc::hir::map::DefCollector;
 use rustc::middle::stability;
 use rustc::{ty, lint, span_bug};
-use syntax::ast::{self, Ident, ItemKind};
-use syntax::attr::{self, StabilityLevel};
+use syntax::ast::{self, Ident};
+use syntax::attr::StabilityLevel;
 use syntax::edition::Edition;
 use syntax::ext::base::{self, Indeterminate, SpecialDerives};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
@@ -115,21 +114,6 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
     }
 }
 
-fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
-    if attr::contains_name(&item.attrs, sym::proc_macro) {
-        return Some((MacroKind::Bang, item.ident, item.span));
-    } else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
-        return Some((MacroKind::Attr, item.ident, item.span));
-    } else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
-        if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
-            if let Some(ident) = nested_meta.ident() {
-                return Some((MacroKind::Derive, ident, ident.span));
-            }
-        }
-    }
-    None
-}
-
 impl<'a> base::Resolver for Resolver<'a> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
@@ -887,62 +871,4 @@ impl<'a> Resolver<'a> {
 
         Lrc::new(result)
     }
-
-    pub fn define_macro(
-        &mut self, item: &ast::Item, parent_scope: &ParentScope<'a>,
-    ) -> LegacyScope<'a> {
-        let expansion = parent_scope.expansion;
-        let (ext, ident, span, is_legacy) = match &item.node {
-            ItemKind::MacroDef(def) => {
-                let ext = self.compile_macro(item, self.session.edition());
-                (ext, item.ident, item.span, def.legacy)
-            }
-            ItemKind::Fn(..) => match proc_macro_stub(item) {
-                Some((macro_kind, ident, span)) => {
-                    self.proc_macro_stubs.insert(item.id);
-                    (self.dummy_ext(macro_kind), ident, span, false)
-                }
-                None => return parent_scope.legacy,
-            }
-            _ => unreachable!(),
-        };
-
-        let def_id = self.definitions.local_def_id(item.id);
-        let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
-        self.macro_map.insert(def_id, ext);
-        self.local_macro_def_scopes.insert(item.id, parent_scope.module);
-
-        if is_legacy {
-            let ident = ident.modern();
-            self.macro_names.insert(ident);
-            let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
-            let vis = if is_macro_export {
-                ty::Visibility::Public
-            } else {
-                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
-            };
-            let binding = (res, vis, span, expansion).to_name_binding(self.arenas);
-            self.set_binding_parent_module(binding, parent_scope.module);
-            self.all_macros.insert(ident.name, res);
-            if is_macro_export {
-                let module = self.graph_root;
-                self.define(module, ident, MacroNS,
-                            (res, vis, span, expansion, IsMacroExport));
-            } else {
-                self.check_reserved_macro_name(ident, res);
-                self.unused_macros.insert(item.id, span);
-            }
-            LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
-                parent_legacy_scope: parent_scope.legacy, binding, ident
-            }))
-        } else {
-            let module = parent_scope.module;
-            let vis = self.resolve_visibility(&item.vis, parent_scope);
-            if vis != ty::Visibility::Public {
-                self.unused_macros.insert(item.id, span);
-            }
-            self.define(module, ident, MacroNS, (res, vis, span, expansion));
-            parent_scope.legacy
-        }
-    }
 }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index aef586fe43c..5caaebf0e96 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -8,7 +8,6 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro
 use crate::{Resolver, ResolutionError, Segment};
 use crate::{names_to_string, module_to_string};
 use crate::ModuleKind;
-use crate::build_reduced_graph::BuildReducedGraphVisitor;
 use crate::diagnostics::Suggestion;
 
 use errors::Applicability;
@@ -27,7 +26,7 @@ use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
 
-use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
+use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
 use syntax::ext::hygiene::ExpnId;
 use syntax::symbol::kw;
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -153,10 +152,14 @@ impl<'a> NameResolution<'a> {
                self.single_imports.is_empty() { Some(binding) } else { None }
         })
     }
+
+    crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) {
+        self.single_imports.insert(PtrKey(directive));
+    }
 }
 
 impl<'a> Resolver<'a> {
-    fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
+    crate fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
                   -> &'a RefCell<NameResolution<'a>> {
         *module.resolutions.borrow_mut().entry((ident.modern(), ns))
                .or_insert_with(|| self.arenas.alloc_name_resolution())
@@ -417,57 +420,7 @@ impl<'a> Resolver<'a> {
         // No resolution and no one else can define the name - determinate error.
         Err((Determined, Weak::No))
     }
-}
-
-impl<'a> BuildReducedGraphVisitor<'_, 'a> {
-    // Add an import directive to the current module.
-    pub fn add_import_directive(&mut self,
-                                module_path: Vec<Segment>,
-                                subclass: ImportDirectiveSubclass<'a>,
-                                span: Span,
-                                id: NodeId,
-                                item: &ast::Item,
-                                root_span: Span,
-                                root_id: NodeId,
-                                vis: ty::Visibility,
-                                parent_scope: ParentScope<'a>) {
-        let current_module = parent_scope.module;
-        let directive = self.r.arenas.alloc_import_directive(ImportDirective {
-            parent_scope,
-            module_path,
-            imported_module: Cell::new(None),
-            subclass,
-            span,
-            id,
-            use_span: item.span,
-            use_span_with_attributes: item.span_with_attributes(),
-            has_attributes: !item.attrs.is_empty(),
-            root_span,
-            root_id,
-            vis: Cell::new(vis),
-            used: Cell::new(false),
-        });
-
-        debug!("add_import_directive({:?})", directive);
-
-        self.r.indeterminate_imports.push(directive);
-        match directive.subclass {
-            SingleImport { target, type_ns_only, .. } => {
-                self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
-                    let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
-                    resolution.single_imports.insert(PtrKey(directive));
-                });
-            }
-            // We don't add prelude imports to the globs since they only affect lexical scopes,
-            // which are not relevant to import resolution.
-            GlobImport { is_prelude: true, .. } => {}
-            GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
-            _ => unreachable!(),
-        }
-    }
-}
 
-impl<'a> Resolver<'a> {
     // Given a binding and an import directive that resolves to it,
     // return the corresponding binding defined by the import directive.
     crate fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)