about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-05 21:18:50 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-10 13:15:15 +0300
commite2e8746acc1d4fd236552a59f54b732680b4524e (patch)
treedec766d81966df1c227c3ee40aabe3072c0df202
parentd19a359444295bab01de7ff44a9d72302e573bc9 (diff)
downloadrust-e2e8746acc1d4fd236552a59f54b732680b4524e.tar.gz
rust-e2e8746acc1d4fd236552a59f54b732680b4524e.zip
resolve: Move late resolution into a separate visitor
Move `Resolver` fields specific to late resolution to the new visitor.
The `current_module` field from `Resolver` is replaced with two `current_module`s in `LateResolutionVisitor` and `BuildReducedGraphVisitor`.
Outside of those visitors `current_module` is replaced by passing `parent_scope` to more functions and using the parent module from it.

Visibility resolution no longer have access to later resolution methods and has to use early resolution, so its diagnostics in case of errors regress slightly.
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs111
-rw-r--r--src/librustc_resolve/check_unused.rs4
-rw-r--r--src/librustc_resolve/diagnostics.rs30
-rw-r--r--src/librustc_resolve/lib.rs417
-rw-r--r--src/librustc_resolve/macros.rs61
-rw-r--r--src/librustc_resolve/resolve_imports.rs53
-rw-r--r--src/test/ui/hygiene/privacy-early.rs17
-rw-r--r--src/test/ui/hygiene/privacy-early.stderr21
-rw-r--r--src/test/ui/resolve/resolve-bad-visibility.rs4
-rw-r--r--src/test/ui/resolve/resolve-bad-visibility.stderr21
-rw-r--r--src/test/ui/resolve/visibility-indeterminate.rs5
-rw-r--r--src/test/ui/resolve/visibility-indeterminate.stderr19
-rw-r--r--src/test/ui/span/visibility-ty-params.stderr14
13 files changed, 477 insertions, 300 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 9d01f330029..668daaba643 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -19,6 +19,7 @@ use rustc::middle::cstore::CrateStore;
 use rustc_metadata::cstore::LoadedMacro;
 
 use std::cell::Cell;
+use std::ops::{Deref, DerefMut};
 use std::ptr;
 use rustc_data_structures::sync::Lrc;
 
@@ -115,7 +116,7 @@ impl<'a> Resolver<'a> {
         parent_prefix: &[Segment],
         nested: bool,
         // The whole `use` item
-        parent_scope: ParentScope<'a>,
+        parent_scope: &ParentScope<'a>,
         item: &Item,
         vis: ty::Visibility,
         root_span: Span,
@@ -249,7 +250,7 @@ impl<'a> Resolver<'a> {
                     root_span,
                     item.id,
                     vis,
-                    parent_scope,
+                    parent_scope.clone(),
                 );
             }
             ast::UseTreeKind::Glob => {
@@ -266,7 +267,7 @@ impl<'a> Resolver<'a> {
                     root_span,
                     item.id,
                     vis,
-                    parent_scope,
+                    parent_scope.clone(),
                 );
             }
             ast::UseTreeKind::Nested(ref items) => {
@@ -297,7 +298,7 @@ impl<'a> Resolver<'a> {
                         // This particular use tree
                         tree, id, &prefix, true,
                         // The whole `use` item
-                        parent_scope.clone(), item, vis, root_span,
+                        parent_scope, item, vis, root_span,
                     );
                 }
 
@@ -327,14 +328,16 @@ impl<'a> Resolver<'a> {
             }
         }
     }
+}
 
+impl<'a> BuildReducedGraphVisitor<'_, 'a> {
     /// Constructs the reduced graph for one item.
-    fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
+    fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: &ParentScope<'a>) {
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
         let ident = item.ident.gensym_if_underscore();
         let sp = item.span;
-        let vis = self.resolve_visibility(&item.vis);
+        let vis = self.resolve_visibility(&item.vis, parent_scope);
 
         match item.node {
             ItemKind::Use(ref use_tree) => {
@@ -361,7 +364,9 @@ impl<'a> Resolver<'a> {
                 } else if orig_name == Some(kw::SelfLower) {
                     self.graph_root
                 } else {
-                    let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
+                    let crate_id = self.resolver.crate_loader.process_extern_crate(
+                        item, &self.resolver.definitions
+                    );
                     self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
                 };
 
@@ -372,13 +377,13 @@ impl<'a> Resolver<'a> {
                     }
                 }
 
-                let used = self.process_legacy_macro_imports(item, module, &parent_scope);
+                let used = self.process_legacy_macro_imports(item, module, parent_scope);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
                     root_id: item.id,
                     id: item.id,
-                    parent_scope,
+                    parent_scope: parent_scope.clone(),
                     imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
                     subclass: ImportDirectiveSubclass::ExternCrate {
                         source: orig_name,
@@ -395,7 +400,7 @@ impl<'a> Resolver<'a> {
                 });
                 self.potentially_unused_imports.push(directive);
                 let imported_binding = self.import(binding, directive);
-                if ptr::eq(self.current_module, self.graph_root) {
+                if ptr::eq(parent, self.graph_root) {
                     if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
                         if expansion != ExpnId::root() && orig_name.is_some() &&
                            entry.extern_crate_item.is_none() {
@@ -455,7 +460,7 @@ impl<'a> Resolver<'a> {
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
-                self.define_macro(item, expansion, &mut LegacyScope::Empty);
+                self.define_macro(item, parent_scope);
             }
 
             // These items live in the type namespace.
@@ -511,8 +516,8 @@ impl<'a> Resolver<'a> {
 
                 // Record field names for error reporting.
                 let field_names = struct_def.fields().iter().filter_map(|field| {
-                    let field_vis = self.resolve_visibility(&field.vis);
-                    if ctor_vis.is_at_least(field_vis, &*self) {
+                    let field_vis = self.resolve_visibility(&field.vis, parent_scope);
+                    if ctor_vis.is_at_least(field_vis, &*self.resolver) {
                         ctor_vis = field_vis;
                     }
                     field.ident.map(|ident| ident.name)
@@ -538,7 +543,7 @@ impl<'a> Resolver<'a> {
 
                 // Record field names for error reporting.
                 let field_names = vdata.fields().iter().filter_map(|field| {
-                    self.resolve_visibility(&field.vis);
+                    self.resolve_visibility(&field.vis, parent_scope);
                     field.ident.map(|ident| ident.name)
                 }).collect();
                 let item_def_id = self.definitions.local_def_id(item.id);
@@ -614,7 +619,13 @@ impl<'a> Resolver<'a> {
             ForeignItemKind::Macro(_) => unreachable!(),
         };
         let parent = self.current_module;
-        let vis = self.resolve_visibility(&item.vis);
+        let parent_scope = &ParentScope {
+            module: self.current_module,
+            expansion: self.expansion,
+            legacy: self.current_legacy_scope,
+            derives: Vec::new(),
+        };
+        let vis = self.resolver.resolve_visibility(&item.vis, parent_scope);
         self.define(parent, item.ident, ns, (res, vis, item.span, expn_id));
     }
 
@@ -630,7 +641,9 @@ impl<'a> Resolver<'a> {
             self.current_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,
@@ -804,7 +817,9 @@ impl<'a> Resolver<'a> {
             self.session.struct_span_err(span, &msg).note(note).emit();
         }
     }
+}
 
+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 {
@@ -873,7 +888,7 @@ impl<'a> Resolver<'a> {
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     MacroNS,
-                    None,
+                    parent_scope,
                     false,
                     ident.span,
                 );
@@ -918,22 +933,36 @@ impl<'a> Resolver<'a> {
 
 pub struct BuildReducedGraphVisitor<'a, 'b> {
     pub resolver: &'a mut Resolver<'b>,
+    pub current_module: Module<'b>,
     pub current_legacy_scope: LegacyScope<'b>,
     pub expansion: ExpnId,
 }
 
+impl<'b> Deref for BuildReducedGraphVisitor<'_, 'b> {
+    type Target = Resolver<'b>;
+    fn deref(&self) -> &Self::Target {
+        self.resolver
+    }
+}
+
+impl<'b> DerefMut for BuildReducedGraphVisitor<'_, 'b> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        self.resolver
+    }
+}
+
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
         let invoc_id = id.placeholder_to_expn_id();
 
-        self.resolver.current_module.unresolved_invocations.borrow_mut().insert(invoc_id);
+        self.current_module.unresolved_invocations.borrow_mut().insert(invoc_id);
 
-        let invocation_data = self.resolver.arenas.alloc_invocation_data(InvocationData {
-            module: self.resolver.current_module,
+        let invocation_data = self.arenas.alloc_invocation_data(InvocationData {
+            module: self.current_module,
             parent_legacy_scope: self.current_legacy_scope,
             output_legacy_scope: Cell::new(None),
         });
-        let old_invocation_data = self.resolver.invocations.insert(invoc_id, invocation_data);
+        let old_invocation_data = self.invocations.insert(invoc_id, invocation_data);
         assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation");
 
         invocation_data
@@ -959,30 +988,30 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
     method!(visit_ty:        ast::Ty,       ast::TyKind::Mac,         walk_ty);
 
     fn visit_item(&mut self, item: &'a Item) {
+        let parent_scope = &ParentScope {
+            module: self.current_module,
+            expansion: self.expansion,
+            legacy: self.current_legacy_scope,
+            derives: Vec::new(),
+        };
         let macro_use = match item.node {
             ItemKind::MacroDef(..) => {
-                self.resolver.define_macro(item, self.expansion, &mut self.current_legacy_scope);
+                self.current_legacy_scope = self.resolver.define_macro(item, parent_scope);
                 return
             }
             ItemKind::Mac(..) => {
                 self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(item.id));
                 return
             }
-            ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
+            ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
             _ => false,
         };
 
-        let orig_current_module = self.resolver.current_module;
+        let orig_current_module = self.current_module;
         let orig_current_legacy_scope = self.current_legacy_scope;
-        let parent_scope = ParentScope {
-            module: self.resolver.current_module,
-            expansion: self.expansion,
-            legacy: self.current_legacy_scope,
-            derives: Vec::new(),
-        };
-        self.resolver.build_reduced_graph_for_item(item, parent_scope);
+        self.build_reduced_graph_for_item(item, parent_scope);
         visit::walk_item(self, item);
-        self.resolver.current_module = orig_current_module;
+        self.current_module = orig_current_module;
         if !macro_use {
             self.current_legacy_scope = orig_current_legacy_scope;
         }
@@ -1002,21 +1031,21 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
             return;
         }
 
-        self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
+        self.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
         visit::walk_foreign_item(self, foreign_item);
     }
 
     fn visit_block(&mut self, block: &'a Block) {
-        let orig_current_module = self.resolver.current_module;
+        let orig_current_module = self.current_module;
         let orig_current_legacy_scope = self.current_legacy_scope;
-        self.resolver.build_reduced_graph_for_block(block, self.expansion);
+        self.build_reduced_graph_for_block(block, self.expansion);
         visit::walk_block(self, block);
-        self.resolver.current_module = orig_current_module;
+        self.current_module = orig_current_module;
         self.current_legacy_scope = orig_current_legacy_scope;
     }
 
     fn visit_trait_item(&mut self, item: &'a TraitItem) {
-        let parent = self.resolver.current_module;
+        let parent = self.current_module;
 
         if let TraitItemKind::Macro(_) = item.node {
             self.visit_invoc(item.id);
@@ -1024,12 +1053,12 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         }
 
         // Add the item to the trait info.
-        let item_def_id = self.resolver.definitions.local_def_id(item.id);
+        let item_def_id = self.definitions.local_def_id(item.id);
         let (res, ns) = match item.node {
             TraitItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
             TraitItemKind::Method(ref sig, _) => {
                 if sig.decl.has_self() {
-                    self.resolver.has_self.insert(item_def_id);
+                    self.has_self.insert(item_def_id);
                 }
                 (Res::Def(DefKind::Method, item_def_id), ValueNS)
             }
@@ -1040,9 +1069,9 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         let vis = ty::Visibility::Public;
         self.resolver.define(parent, item.ident, ns, (res, vis, item.span, self.expansion));
 
-        self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor
+        self.current_module = parent.parent.unwrap(); // nearest normal ancestor
         visit::walk_trait_item(self, item);
-        self.resolver.current_module = parent;
+        self.current_module = parent;
     }
 
     fn visit_token(&mut self, t: Token) {
@@ -1058,7 +1087,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
         if !attr.is_sugared_doc && is_builtin_attr(attr) {
             let parent_scope = ParentScope {
-                module: self.resolver.current_module.nearest_item_scope(),
+                module: self.current_module.nearest_item_scope(),
                 expansion: self.expansion,
                 legacy: self.current_legacy_scope,
                 // Let's hope discerning built-in attributes from derive helpers is not necessary
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 4fee15c59b3..d733a32c9c3 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -270,10 +270,6 @@ pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) {
         }
     }
 
-    for (id, span) in resolver.unused_labels.iter() {
-        resolver.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
-    }
-
     let mut visitor = UnusedImportCheckVisitor {
         resolver,
         unused_imports: Default::default(),
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index aeb6f23da5a..c1fe7188f6d 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -18,7 +18,7 @@ use syntax_pos::{BytePos, Span};
 
 use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::{is_self_type, is_self_value, path_names_to_string, KNOWN_TOOLS};
-use crate::{CrateLint, LegacyScope, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{CrateLint, LateResolutionVisitor, LegacyScope, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, ParentScope, Resolver, RibKind, Scope, ScopeSet, Segment};
 
 type Res = def::Res<ast::NodeId>;
@@ -78,7 +78,7 @@ fn add_module_candidates(
     }
 }
 
-impl<'a> Resolver<'a> {
+impl<'a> LateResolutionVisitor<'a, '_> {
     /// Handles error reporting for `smart_resolve_path_fragment` function.
     /// Creates base error and amends it with one short label and possibly some longer helps/notes.
     pub(crate) fn smart_resolve_report_errors(
@@ -112,7 +112,7 @@ impl<'a> Resolver<'a> {
                 (String::new(), "the crate root".to_string())
             } else {
                 let mod_path = &path[..path.len() - 1];
-                let mod_prefix = match self.resolve_path_without_parent_scope(
+                let mod_prefix = match self.resolve_path(
                     mod_path, Some(TypeNS), false, span, CrateLint::No
                 ) {
                     PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
@@ -288,7 +288,9 @@ impl<'a> Resolver<'a> {
         }
         (err, candidates)
     }
+}
 
+impl<'a> Resolver<'a> {
     fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) {
         // HACK(estebank): find a better way to figure out that this was a
         // parser issue where a struct literal is being used on an expression
@@ -338,7 +340,9 @@ impl<'a> Resolver<'a> {
         }
         return (followed_by_brace, closing_brace)
     }
+}
 
+impl<'a> LateResolutionVisitor<'a, '_> {
     /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
     /// function.
     /// Returns `true` if able to provide context-dependent help.
@@ -457,7 +461,7 @@ impl<'a> Resolver<'a> {
             (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
                 if let Some((ctor_def, ctor_vis))
                         = self.struct_constructors.get(&def_id).cloned() {
-                    let accessible_ctor = self.is_accessible(ctor_vis);
+                    let accessible_ctor = self.is_accessible_from(ctor_vis, self.current_module);
                     if is_expected(ctor_def) && !accessible_ctor {
                         err.span_label(
                             span,
@@ -532,11 +536,12 @@ impl<'a> Resolver<'a> {
 
         // Look for associated items in the current trait.
         if let Some((module, _)) = self.current_trait_ref {
+            let parent_scope = &self.parent_scope();
             if let Ok(binding) = self.resolve_ident_in_module(
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     ns,
-                    None,
+                    parent_scope,
                     false,
                     module.span,
                 ) {
@@ -553,7 +558,9 @@ impl<'a> Resolver<'a> {
 
         None
     }
+}
 
+impl<'a> Resolver<'a> {
     /// Lookup typo candidate in scope for a macro or import.
     fn early_lookup_typo_candidate(
         &mut self,
@@ -569,9 +576,10 @@ impl<'a> Resolver<'a> {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
                     if filter_fn(res) {
                         for derive in &parent_scope.derives {
-                            let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
+                            let parent_scope =
+                                &ParentScope { derives: Vec::new(), ..*parent_scope };
                             if let Ok((Some(ext), _)) = this.resolve_macro_path(
-                                derive, Some(MacroKind::Derive), &parent_scope, false, false
+                                derive, Some(MacroKind::Derive), parent_scope, false, false
                             ) {
                                 suggestions.extend(ext.helper_attrs.iter().map(|name| {
                                     TypoSuggestion::from_res(*name, res)
@@ -682,7 +690,9 @@ impl<'a> Resolver<'a> {
             _ => None,
         }
     }
+}
 
+impl<'a> LateResolutionVisitor<'a, '_> {
     fn lookup_typo_candidate(
         &mut self,
         path: &[Segment],
@@ -750,7 +760,7 @@ impl<'a> Resolver<'a> {
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
-            if let PathResult::Module(module) = self.resolve_path_without_parent_scope(
+            if let PathResult::Module(module) = self.resolve_path(
                 mod_path, Some(TypeNS), false, span, CrateLint::No
             ) {
                 if let ModuleOrUniformRoot::Module(module) = module {
@@ -774,7 +784,9 @@ impl<'a> Resolver<'a> {
             _ => None,
         }
     }
+}
 
+impl<'a> Resolver<'a> {
     fn lookup_import_candidates_from_module<FilterFn>(&mut self,
                                           lookup_ident: Ident,
                                           namespace: Namespace,
@@ -969,7 +981,7 @@ impl<'a> Resolver<'a> {
     ) {
         let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
         let suggestion = self.early_lookup_typo_candidate(
-            ScopeSet::Macro(macro_kind), &parent_scope, ident, is_expected
+            ScopeSet::Macro(macro_kind), parent_scope, ident, is_expected
         );
         add_typo_suggestion(err, suggestion, ident.span);
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ce2bc79ff60..e11413fcda9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -59,6 +59,7 @@ use log::debug;
 
 use std::cell::{Cell, RefCell};
 use std::{cmp, fmt, iter, mem, ptr};
+use std::ops::{Deref, DerefMut};
 use std::collections::BTreeSet;
 use std::mem::replace;
 use rustc_data_structures::ptr_key::PtrKey;
@@ -537,35 +538,22 @@ enum PathSource<'a> {
     TupleStruct,
     // `m::A::B` in `<T as m::A>::B::C`.
     TraitItem(Namespace),
-    // Path in `pub(path)`
-    Visibility,
 }
 
 impl<'a> PathSource<'a> {
     fn namespace(self) -> Namespace {
         match self {
-            PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
-            PathSource::Visibility => TypeNS,
+            PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
             PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
             PathSource::TraitItem(ns) => ns,
         }
     }
 
-    fn global_by_default(self) -> bool {
-        match self {
-            PathSource::Visibility => true,
-            PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
-            PathSource::Struct | PathSource::TupleStruct |
-            PathSource::Trait(_) | PathSource::TraitItem(..) => false,
-        }
-    }
-
     fn defer_to_typeck(self) -> bool {
         match self {
             PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
             PathSource::Struct | PathSource::TupleStruct => true,
-            PathSource::Trait(_) | PathSource::TraitItem(..) |
-            PathSource::Visibility => false,
+            PathSource::Trait(_) | PathSource::TraitItem(..) => false,
         }
     }
 
@@ -576,7 +564,6 @@ impl<'a> PathSource<'a> {
             PathSource::Pat => "unit struct/variant or constant",
             PathSource::Struct => "struct, variant or union type",
             PathSource::TupleStruct => "tuple struct/variant",
-            PathSource::Visibility => "module",
             PathSource::TraitItem(ns) => match ns {
                 TypeNS => "associated type",
                 ValueNS => "method or associated constant",
@@ -655,10 +642,6 @@ impl<'a> PathSource<'a> {
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                 _ => false,
             },
-            PathSource::Visibility => match res {
-                Res::Def(DefKind::Mod, _) => true,
-                _ => false,
-            },
         }
     }
 
@@ -675,8 +658,6 @@ impl<'a> PathSource<'a> {
         __diagnostic_used!(E0574);
         __diagnostic_used!(E0575);
         __diagnostic_used!(E0576);
-        __diagnostic_used!(E0577);
-        __diagnostic_used!(E0578);
         match (self, has_unexpected_resolution) {
             (PathSource::Trait(_), true) => "E0404",
             (PathSource::Trait(_), false) => "E0405",
@@ -690,8 +671,6 @@ impl<'a> PathSource<'a> {
             (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
             (PathSource::TraitItem(..), true) => "E0575",
             (PathSource::TraitItem(..), false) => "E0576",
-            (PathSource::Visibility, true) => "E0577",
-            (PathSource::Visibility, false) => "E0578",
         }
     }
 }
@@ -801,8 +780,80 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
     }
 }
 
+struct LateResolutionVisitor<'a, 'b> {
+    resolver: &'b mut Resolver<'a>,
+
+    /// The module that represents the current item scope.
+    current_module: Module<'a>,
+
+    /// The current set of local scopes for types and values.
+    /// FIXME #4948: Reuse ribs to avoid allocation.
+    ribs: PerNS<Vec<Rib<'a>>>,
+
+    /// The current set of local scopes, for labels.
+    label_ribs: Vec<Rib<'a, NodeId>>,
+
+    /// The trait that the current context can refer to.
+    current_trait_ref: Option<(Module<'a>, TraitRef)>,
+
+    /// The current trait's associated types' ident, used for diagnostic suggestions.
+    current_trait_assoc_types: Vec<Ident>,
+
+    /// The current self type if inside an impl (used for better errors).
+    current_self_type: Option<Ty>,
+
+    /// The current self item if inside an ADT (used for better errors).
+    current_self_item: Option<NodeId>,
+
+    /// A list of labels as of yet unused. Labels will be removed from this map when
+    /// they are used (in a `break` or `continue` statement)
+    unused_labels: FxHashMap<NodeId, Span>,
+
+    /// Only used for better errors on `fn(): fn()`.
+    current_type_ascription: Vec<Span>,
+}
+
+impl<'a, 'b> LateResolutionVisitor<'a, '_> {
+    fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
+        let graph_root = resolver.graph_root;
+        LateResolutionVisitor {
+            resolver,
+            current_module: graph_root,
+            ribs: PerNS {
+                value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+                type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+                macro_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+            },
+            label_ribs: Vec::new(),
+            current_trait_ref: None,
+            current_trait_assoc_types: Vec::new(),
+            current_self_type: None,
+            current_self_item: None,
+            unused_labels: Default::default(),
+            current_type_ascription: Vec::new(),
+        }
+    }
+
+    fn parent_scope(&self) -> ParentScope<'a> {
+        ParentScope { module: self.current_module, ..self.dummy_parent_scope() }
+    }
+}
+
+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 Resolver<'a> {
+impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
     fn visit_item(&mut self, item: &'tcx Item) {
         self.resolve_item(item);
     }
@@ -1587,28 +1638,6 @@ pub struct Resolver<'a> {
     /// All non-determined imports.
     indeterminate_imports: Vec<&'a ImportDirective<'a>>,
 
-    /// The module that represents the current item scope.
-    current_module: Module<'a>,
-
-    /// The current set of local scopes for types and values.
-    /// FIXME #4948: Reuse ribs to avoid allocation.
-    ribs: PerNS<Vec<Rib<'a>>>,
-
-    /// The current set of local scopes, for labels.
-    label_ribs: Vec<Rib<'a, NodeId>>,
-
-    /// The trait that the current context can refer to.
-    current_trait_ref: Option<(Module<'a>, TraitRef)>,
-
-    /// The current trait's associated types' ident, used for diagnostic suggestions.
-    current_trait_assoc_types: Vec<Ident>,
-
-    /// The current self type if inside an impl (used for better errors).
-    current_self_type: Option<Ty>,
-
-    /// The current self item if inside an ADT (used for better errors).
-    current_self_item: Option<NodeId>,
-
     /// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
     /// We are resolving a last import segment during import validation.
     last_import_segment: bool,
@@ -1655,10 +1684,6 @@ pub struct Resolver<'a> {
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
 
-    /// A list of labels as of yet unused. Labels will be removed from this map when
-    /// they are used (in a `break` or `continue` statement)
-    pub unused_labels: FxHashMap<NodeId, Span>,
-
     /// Privacy errors are delayed until the end in order to deduplicate them.
     privacy_errors: Vec<PrivacyError<'a>>,
     /// Ambiguity errors are delayed for deduplication.
@@ -1703,9 +1728,6 @@ pub struct Resolver<'a> {
     /// it's not used during normal resolution, only for better error reporting.
     struct_constructors: DefIdMap<(Res, ty::Visibility)>,
 
-    /// Only used for better errors on `fn(): fn()`.
-    current_type_ascription: Vec<Span>,
-
     injected_crate: Option<Module<'a>>,
 
     /// Features enabled for this crate.
@@ -1872,8 +1894,8 @@ impl<'a> Resolver<'a> {
         let span = path.span;
         let path = Segment::from_path(&path);
         // FIXME(Manishearth): intra-doc links won't get warned of epoch changes.
-        match self.resolve_path_without_parent_scope(&path, Some(namespace), true,
-                                                               span, CrateLint::No) {
+        let parent_scope = &self.dummy_parent_scope();
+        match self.resolve_path(&path, Some(namespace), parent_scope, true, span, CrateLint::No) {
             PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
                 Ok(module.res().unwrap()),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
@@ -1969,18 +1991,6 @@ impl<'a> Resolver<'a> {
             determined_imports: Vec::new(),
             indeterminate_imports: Vec::new(),
 
-            current_module: graph_root,
-            ribs: PerNS {
-                value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                macro_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-            },
-            label_ribs: Vec::new(),
-
-            current_trait_ref: None,
-            current_trait_assoc_types: Vec::new(),
-            current_self_type: None,
-            current_self_item: None,
             last_import_segment: false,
             blacklisted_binding: None,
 
@@ -2002,8 +2012,6 @@ impl<'a> Resolver<'a> {
             maybe_unused_trait_imports: Default::default(),
             maybe_unused_extern_crates: Vec::new(),
 
-            unused_labels: FxHashMap::default(),
-
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
             use_injections: Vec::new(),
@@ -2036,7 +2044,6 @@ impl<'a> Resolver<'a> {
             unused_macros: Default::default(),
             proc_macro_stubs: Default::default(),
             special_derives: Default::default(),
-            current_type_ascription: Vec::new(),
             injected_crate: None,
             active_features:
                 features.declared_lib_features.iter().map(|(feat, ..)| *feat)
@@ -2089,10 +2096,13 @@ impl<'a> Resolver<'a> {
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
         ImportResolver { resolver: self }.finalize_imports();
-        self.current_module = self.graph_root;
-        self.finalize_current_module_macro_resolutions();
 
-        visit::walk_crate(self, krate);
+        self.finalize_current_module_macro_resolutions(self.graph_root);
+        let mut late_resolution_visitor = LateResolutionVisitor::new(self);
+        visit::walk_crate(&mut late_resolution_visitor, krate);
+        for (id, span) in late_resolution_visitor.unused_labels.iter() {
+            self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
+        }
 
         check_unused::check_crate(self, krate);
         self.report_errors(krate);
@@ -2287,7 +2297,9 @@ impl<'a> Resolver<'a> {
 
         None
     }
+}
 
+impl<'a> Resolver<'a> {
     /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
     /// More specifically, we proceed up the hierarchy of scopes and return the binding for
     /// `ident` in the first scope that defines it (or None if no scopes define it).
@@ -2308,8 +2320,10 @@ impl<'a> Resolver<'a> {
     fn resolve_ident_in_lexical_scope(&mut self,
                                       mut ident: Ident,
                                       ns: Namespace,
+                                      parent_scope: &ParentScope<'a>,
                                       record_used_id: Option<NodeId>,
-                                      path_span: Span)
+                                      path_span: Span,
+                                      ribs: &[Rib<'a>])
                                       -> Option<LexicalScopeBinding<'a>> {
         assert!(ns == TypeNS || ns == ValueNS);
         if ident.name == kw::Invalid {
@@ -2331,23 +2345,23 @@ impl<'a> Resolver<'a> {
         // Walk backwards up the ribs in scope.
         let record_used = record_used_id.is_some();
         let mut module = self.graph_root;
-        for i in (0 .. self.ribs[ns].len()).rev() {
-            debug!("walk rib\n{:?}", self.ribs[ns][i].bindings);
+        for i in (0 .. ribs.len()).rev() {
+            debug!("walk rib\n{:?}", ribs[i].bindings);
             // Use the rib kind to determine whether we are resolving parameters
             // (modern hygiene) or local variables (legacy hygiene).
-            let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind {
+            let rib_ident = if let AssocItemRibKind | ItemRibKind = ribs[i].kind {
                 modern_ident
             } else {
                 ident
             };
-            if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() {
+            if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(
-                    self.validate_res_from_ribs(ns, i, res, record_used, path_span),
+                    self.validate_res_from_ribs(i, res, record_used, path_span, ribs),
                 ));
             }
 
-            module = match self.ribs[ns][i].kind {
+            module = match ribs[i].kind {
                 ModuleRibKind(module) => module,
                 MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
                     // If an invocation of this macro created `ident`, give up on `ident`
@@ -2358,10 +2372,12 @@ impl<'a> Resolver<'a> {
                 _ => continue,
             };
 
+
             let item = self.resolve_ident_in_module_unadjusted(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
+                parent_scope,
                 record_used,
                 path_span,
             );
@@ -2386,16 +2402,15 @@ impl<'a> Resolver<'a> {
                 self.hygienic_lexical_parent(module, &mut ident.span)
             };
             module = unwrap_or!(opt_module, break);
-            let orig_current_module = self.current_module;
-            self.current_module = module; // Lexical resolutions can never be a privacy error.
+            let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() };
             let result = self.resolve_ident_in_module_unadjusted(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
+                adjusted_parent_scope,
                 record_used,
                 path_span,
             );
-            self.current_module = orig_current_module;
 
             match result {
                 Ok(binding) => {
@@ -2433,6 +2448,7 @@ impl<'a> Resolver<'a> {
                     ModuleOrUniformRoot::Module(prelude),
                     ident,
                     ns,
+                    parent_scope,
                     false,
                     path_span,
                 ) {
@@ -2498,7 +2514,7 @@ impl<'a> Resolver<'a> {
         module: ModuleOrUniformRoot<'a>,
         ident: Ident,
         ns: Namespace,
-        parent_scope: Option<&ParentScope<'a>>,
+        parent_scope: &ParentScope<'a>,
         record_used: bool,
         path_span: Span
     ) -> Result<&'a NameBinding<'a>, Determinacy> {
@@ -2512,15 +2528,18 @@ impl<'a> Resolver<'a> {
         module: ModuleOrUniformRoot<'a>,
         mut ident: Ident,
         ns: Namespace,
-        parent_scope: Option<&ParentScope<'a>>,
+        parent_scope: &ParentScope<'a>,
         record_used: bool,
         path_span: Span
     ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
-        let orig_current_module = self.current_module;
+        let tmp_parent_scope;
+        let mut adjusted_parent_scope = parent_scope;
         match module {
-            ModuleOrUniformRoot::Module(module) => {
-                if let Some(def) = ident.span.modernize_and_adjust(module.expansion) {
-                    self.current_module = self.macro_def_scope(def);
+            ModuleOrUniformRoot::Module(m) => {
+                if let Some(def) = ident.span.modernize_and_adjust(m.expansion) {
+                    tmp_parent_scope =
+                        ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() };
+                    adjusted_parent_scope = &tmp_parent_scope;
                 }
             }
             ModuleOrUniformRoot::ExternPrelude => {
@@ -2532,9 +2551,8 @@ impl<'a> Resolver<'a> {
             }
         }
         let result = self.resolve_ident_in_module_unadjusted_ext(
-            module, ident, ns, parent_scope, false, record_used, path_span,
+            module, ident, ns, adjusted_parent_scope, false, record_used, path_span,
         );
-        self.current_module = orig_current_module;
         result
     }
 
@@ -2587,7 +2605,9 @@ impl<'a> Resolver<'a> {
         }
         module
     }
+}
 
+impl<'a> LateResolutionVisitor<'a, '_> {
     // AST resolution
     //
     // We maintain a list of value ribs and type ribs.
@@ -2606,8 +2626,32 @@ impl<'a> Resolver<'a> {
     // generate a fake "implementation scope" containing all the
     // implementations thus found, for compatibility with old resolve pass.
 
+    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]
+        )
+    }
+
+    fn resolve_path(
+        &mut self,
+        path: &[Segment],
+        opt_ns: Option<Namespace>, // `None` indicates a module path in import
+        record_used: bool,
+        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
+        )
+    }
+
     pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
-        where F: FnOnce(&mut Resolver<'_>) -> 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
@@ -2617,7 +2661,7 @@ impl<'a> Resolver<'a> {
             self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
             self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
-            self.finalize_current_module_macro_resolutions();
+            self.resolver.finalize_current_module_macro_resolutions(self.current_module);
             let ret = f(self);
 
             self.current_module = orig_module;
@@ -2827,7 +2871,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_generic_param_rib<'b, F>(&'b mut self, generic_params: GenericParameters<'a, 'b>, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         debug!("with_generic_param_rib");
         match generic_params {
@@ -2901,7 +2945,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_label_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         self.label_ribs.push(Rib::new(NormalRibKind));
         f(self);
@@ -2909,7 +2953,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_item_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         self.ribs[ValueNS].push(Rib::new(ItemRibKind));
         self.ribs[TypeNS].push(Rib::new(ItemRibKind));
@@ -2919,7 +2963,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_constant_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         debug!("with_constant_rib");
         self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
@@ -2930,7 +2974,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
-        where F: FnOnce(&mut Resolver<'_>) -> T
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
     {
         // Handle nested impls (inside fn bodies)
         let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
@@ -2940,7 +2984,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_current_self_item<T, F>(&mut self, self_item: &Item, f: F) -> T
-        where F: FnOnce(&mut Resolver<'_>) -> T
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
     {
         let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
         let result = f(self);
@@ -2950,7 +2994,7 @@ impl<'a> Resolver<'a> {
 
     /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
     fn with_trait_items<T, F>(&mut self, trait_items: &Vec<TraitItem>, f: F) -> T
-        where F: FnOnce(&mut Resolver<'_>) -> T
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
     {
         let trait_assoc_types = replace(
             &mut self.current_trait_assoc_types,
@@ -2966,7 +3010,7 @@ impl<'a> Resolver<'a> {
 
     /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
     fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
-        where F: FnOnce(&mut Resolver<'_>, Option<DefId>) -> T
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>, Option<DefId>) -> T
     {
         let mut new_val = None;
         let mut new_id = None;
@@ -2984,7 +3028,7 @@ impl<'a> Resolver<'a> {
                 new_id = Some(res.def_id());
                 let span = trait_ref.path.span;
                 if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
-                    self.resolve_path_without_parent_scope(
+                    self.resolve_path(
                         &path,
                         Some(TypeNS),
                         false,
@@ -3003,7 +3047,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_self_rib<F>(&mut self, self_res: Res, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         let mut self_type_rib = Rib::new(NormalRibKind);
 
@@ -3015,7 +3059,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         let self_res = Res::SelfCtor(impl_id);
         let mut self_type_rib = Rib::new(NormalRibKind);
@@ -3053,8 +3097,9 @@ impl<'a> Resolver<'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.resolve_visibility(&impl_item.vis);
-
+                                    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);
@@ -3129,11 +3174,12 @@ impl<'a> Resolver<'a> {
         // 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(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
-                None,
+                parent_scope,
                 false,
                 span,
             ).is_err() {
@@ -3282,7 +3328,7 @@ impl<'a> Resolver<'a> {
             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();
+            self.resolver.finalize_current_module_macro_resolutions(self.current_module);
         } else {
             self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
@@ -3497,7 +3543,6 @@ impl<'a> Resolver<'a> {
             ns,
             span,
             source.defer_to_typeck(),
-            source.global_by_default(),
             crate_lint,
         ) {
             Some(partial_res) if partial_res.unresolved_segments() == 0 => {
@@ -3510,7 +3555,8 @@ impl<'a> Resolver<'a> {
                     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() {
-                            if is_expected(ctor_res) && self.is_accessible(ctor_vis) {
+                            if is_expected(ctor_res) &&
+                               self.is_accessible_from(ctor_vis, self.current_module) {
                                 let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
                                 self.session.buffer_lint(lint, id, span,
                                     "private struct constructors are not usable through \
@@ -3540,8 +3586,7 @@ impl<'a> Resolver<'a> {
                     let cl = CrateLint::No;
                     let ns = Some(ns);
                     if let PathResult::Module(_) | PathResult::NonModule(_) =
-                        self.resolve_path_without_parent_scope(&std_path, ns, false, span, cl)
-                    {
+                            self.resolve_path(&std_path, ns, false, span, cl) {
                         // check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
                         let item_span = path.iter().last().map(|segment| segment.ident.span)
                             .unwrap_or(span);
@@ -3678,13 +3723,12 @@ impl<'a> Resolver<'a> {
         primary_ns: Namespace,
         span: Span,
         defer_to_typeck: bool,
-        global_by_default: bool,
         crate_lint: CrateLint,
     ) -> Option<PartialRes> {
         let mut fin_res = None;
         for (i, ns) in [primary_ns, TypeNS, ValueNS].iter().cloned().enumerate() {
             if i == 0 || ns != primary_ns {
-                match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) {
+                match self.resolve_qpath(id, qself, path, ns, span, crate_lint) {
                     // If defer_to_typeck, then resolution > no resolution,
                     // otherwise full resolution > partial resolution > no resolution.
                     Some(partial_res) if partial_res.unresolved_segments() == 0 ||
@@ -3700,10 +3744,9 @@ impl<'a> Resolver<'a> {
         if qself.is_none() {
             let path_seg = |seg: &Segment| ast::PathSegment::from_ident(seg.ident);
             let path = Path { segments: path.iter().map(path_seg).collect(), span };
-            let parent_scope =
-                ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
+            let parent_scope = &self.parent_scope();
             if let Ok((_, res)) =
-                    self.resolve_macro_path(&path, None, &parent_scope, false, false) {
+                    self.resolve_macro_path(&path, None, parent_scope, false, false) {
                 return Some(PartialRes::new(res));
             }
         }
@@ -3719,18 +3762,15 @@ impl<'a> Resolver<'a> {
         path: &[Segment],
         ns: Namespace,
         span: Span,
-        global_by_default: bool,
         crate_lint: CrateLint,
     ) -> Option<PartialRes> {
         debug!(
-            "resolve_qpath(id={:?}, qself={:?}, path={:?}, \
-             ns={:?}, span={:?}, global_by_default={:?})",
+            "resolve_qpath(id={:?}, qself={:?}, path={:?}, ns={:?}, span={:?})",
             id,
             qself,
             path,
             ns,
             span,
-            global_by_default,
         );
 
         if let Some(qself) = qself {
@@ -3779,13 +3819,7 @@ impl<'a> Resolver<'a> {
             ));
         }
 
-        let result = match self.resolve_path_without_parent_scope(
-            &path,
-            Some(ns),
-            true,
-            span,
-            crate_lint,
-        ) {
+        let result = match self.resolve_path(&path, Some(ns), true, span, crate_lint) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
                 PartialRes::new(module.res().unwrap())
@@ -3820,11 +3854,11 @@ impl<'a> Resolver<'a> {
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
-        if path.len() > 1 && !global_by_default && result.base_res() != Res::Err &&
+        if path.len() > 1 && result.base_res() != Res::Err &&
            path[0].ident.name != kw::PathRoot &&
            path[0].ident.name != kw::DollarCrate {
             let unqualified_result = {
-                match self.resolve_path_without_parent_scope(
+                match self.resolve_path(
                     &[*path.last().unwrap()],
                     Some(ns),
                     false,
@@ -3845,23 +3879,24 @@ impl<'a> Resolver<'a> {
 
         Some(result)
     }
+}
 
-    fn resolve_path_without_parent_scope(
+impl<'a> Resolver<'a> {
+    fn resolve_path(
         &mut self,
         path: &[Segment],
         opt_ns: Option<Namespace>, // `None` indicates a module path in import
+        parent_scope: &ParentScope<'a>,
         record_used: bool,
         path_span: Span,
         crate_lint: CrateLint,
     ) -> PathResult<'a> {
-        // Macro and import paths must have full parent scope available during resolution,
-        // other paths will do okay with parent module alone.
-        assert!(opt_ns != None && opt_ns != Some(MacroNS));
-        let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
-        self.resolve_path(path, opt_ns, &parent_scope, record_used, path_span, crate_lint)
+        self.resolve_path_with_ribs(
+            path, opt_ns, parent_scope, record_used, path_span, crate_lint, &Default::default()
+        )
     }
 
-    fn resolve_path(
+    fn resolve_path_with_ribs(
         &mut self,
         path: &[Segment],
         opt_ns: Option<Namespace>, // `None` indicates a module path in import
@@ -3869,11 +3904,11 @@ impl<'a> Resolver<'a> {
         record_used: bool,
         path_span: Span,
         crate_lint: CrateLint,
+        ribs: &PerNS<Vec<Rib<'a>>>,
     ) -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
         let mut second_binding = None;
-        self.current_module = parent_scope.module;
 
         debug!(
             "resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, \
@@ -3910,7 +3945,7 @@ impl<'a> Resolver<'a> {
                 if allow_super && name == kw::Super {
                     let mut ctxt = ident.span.ctxt().modern();
                     let self_module = match i {
-                        0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
+                        0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
                         _ => match module {
                             Some(ModuleOrUniformRoot::Module(module)) => Some(module),
                             _ => None,
@@ -3935,7 +3970,7 @@ impl<'a> Resolver<'a> {
                     if name == kw::SelfLower {
                         let mut ctxt = ident.span.ctxt().modern();
                         module = Some(ModuleOrUniformRoot::Module(
-                            self.resolve_self(&mut ctxt, self.current_module)));
+                            self.resolve_self(&mut ctxt, parent_scope.module)));
                         continue;
                     }
                     if name == kw::PathRoot && ident.span.rust_2018() {
@@ -3980,7 +4015,9 @@ impl<'a> Resolver<'a> {
             }
 
             let binding = if let Some(module) = module {
-                self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span)
+                self.resolve_ident_in_module(
+                    module, ident, ns, parent_scope, record_used, path_span
+                )
             } else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
                 let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module };
@@ -3989,7 +4026,9 @@ impl<'a> Resolver<'a> {
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
-                match self.resolve_ident_in_lexical_scope(ident, ns, record_used_id, path_span) {
+                match self.resolve_ident_in_lexical_scope(
+                    ident, ns, parent_scope, record_used_id, path_span, &ribs[ns]
+                ) {
                     // we found a locally-imported or available item/module
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                     // we found a local variable or type param
@@ -4176,17 +4215,17 @@ impl<'a> Resolver<'a> {
     // Validate a local resolution (from ribs).
     fn validate_res_from_ribs(
         &mut self,
-        ns: Namespace,
         rib_index: usize,
         res: Res,
         record_used: bool,
         span: Span,
+        all_ribs: &[Rib<'a>],
     ) -> Res {
         debug!("validate_res_from_ribs({:?})", res);
-        let ribs = &self.ribs[ns][rib_index + 1..];
+        let ribs = &all_ribs[rib_index + 1..];
 
         // An invalid forward use of a type parameter from a previous default.
-        if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
+        if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind {
             if record_used {
                 resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam);
             }
@@ -4195,7 +4234,7 @@ impl<'a> Resolver<'a> {
         }
 
         // An invalid use of a type parameter as the type of a const parameter.
-        if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
+        if let TyParamAsConstParamTy = all_ribs[rib_index].kind {
             if record_used {
                 resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
             }
@@ -4288,9 +4327,11 @@ impl<'a> Resolver<'a> {
         }
         res
     }
+}
 
+impl<'a> LateResolutionVisitor<'a, '_> {
     fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F)
-        where F: FnOnce(&mut Resolver<'_>)
+        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
     {
         if let Some(label) = label {
             self.unused_labels.insert(id, label.ident.span);
@@ -4486,11 +4527,12 @@ impl<'a> Resolver<'a> {
         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(
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
-                None,
+                parent_scope,
                 false,
                 module.span,
             ).is_ok() {
@@ -4547,10 +4589,12 @@ impl<'a> Resolver<'a> {
                 ).is_none() {
                     continue
                 }
+                let parent_scope = &self.parent_scope();
                 if self.resolve_ident_in_module_unadjusted(
                     ModuleOrUniformRoot::Module(module),
                     ident,
                     ns,
+                    parent_scope,
                     false,
                     module.span,
                 ).is_ok() {
@@ -4581,7 +4625,9 @@ impl<'a> Resolver<'a> {
         };
         import_ids
     }
+}
 
+impl<'a> Resolver<'a> {
     fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) {
         debug!("(recording res) recording {:?} for {}", resolution, node_id);
         if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) {
@@ -4589,14 +4635,16 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
+    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(self.current_module.normal_ancestor_id)
+                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
@@ -4626,23 +4674,58 @@ impl<'a> Resolver<'a> {
 
                 let segments = crate_root.into_iter()
                     .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
-                let res = self.smart_resolve_path_fragment(
-                    id,
-                    None,
+                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,
-                    PathSource::Visibility,
                     CrateLint::SimplePath(id),
-                ).base_res();
-                if res == Res::Err {
-                    ty::Visibility::Public
-                } else {
-                    let vis = ty::Visibility::Restricted(res.def_id());
-                    if self.is_accessible(vis) {
-                        vis
-                    } else {
-                        self.session.span_err(path.span, "visibilities can only be restricted \
-                                                          to ancestor modules");
+                ) {
+                    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, .. } => {
+                        let err = ResolutionError::FailedToResolve { label, suggestion };
+                        resolve_error(self, span, err);
+                        ty::Visibility::Public
+                    }
+                    PathResult::Indeterminate => {
+                        span_err!(self.session, path.span, E0578,
+                                  "cannot determine resolution for the visibility");
                         ty::Visibility::Public
                     }
                 }
@@ -4650,10 +4733,6 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn is_accessible(&self, vis: ty::Visibility) -> bool {
-        vis.is_accessible_from(self.current_module.normal_ancestor_id, self)
-    }
-
     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 1f534bc41fe..cc89650bc29 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -166,9 +166,8 @@ impl<'a> base::Resolver for Resolver<'a> {
         fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expn_id));
 
         let invocation = self.invocations[&expn_id];
-        self.current_module = invocation.module;
-        self.current_module.unresolved_invocations.borrow_mut().remove(&expn_id);
-        self.current_module.unresolved_invocations.borrow_mut().extend(derives);
+        invocation.module.unresolved_invocations.borrow_mut().remove(&expn_id);
+        invocation.module.unresolved_invocations.borrow_mut().extend(derives);
         let parent_def = self.definitions.invocation_parent(expn_id);
         for &derive_invoc_id in derives {
             self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
@@ -176,6 +175,7 @@ impl<'a> base::Resolver for Resolver<'a> {
         self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
         let mut visitor = BuildReducedGraphVisitor {
             resolver: self,
+            current_module: invocation.module,
             current_legacy_scope: invocation.parent_legacy_scope,
             expansion: expn_id,
         };
@@ -210,10 +210,10 @@ impl<'a> base::Resolver for Resolver<'a> {
                 // will automatically knows about itself.
                 let mut result = Ok(None);
                 if derives.len() > 1 {
-                    let parent_scope = self.invoc_parent_scope(invoc_id, Vec::new());
+                    let parent_scope = &self.invoc_parent_scope(invoc_id, Vec::new());
                     for path in derives {
                         match self.resolve_macro_path(path, Some(MacroKind::Derive),
-                                                      &parent_scope, true, force) {
+                                                      parent_scope, true, force) {
                             Ok((Some(ref ext), _)) if ext.is_derive_copy => {
                                 self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
                                 return Ok(None);
@@ -227,8 +227,8 @@ impl<'a> base::Resolver for Resolver<'a> {
             }
         };
 
-        let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
-        let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, force)?;
+        let parent_scope = &self.invoc_parent_scope(invoc_id, derives_in_scope);
+        let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
 
         let span = invoc.span();
         invoc.expansion_data.id.set_expn_info(ext.expn_info(span, fast_print_path(path)));
@@ -471,9 +471,9 @@ impl<'a> Resolver<'a> {
                 Scope::DeriveHelpers => {
                     let mut result = Err(Determinacy::Determined);
                     for derive in &parent_scope.derives {
-                        let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
+                        let parent_scope = &ParentScope { derives: Vec::new(), ..*parent_scope };
                         match this.resolve_macro_path(derive, Some(MacroKind::Derive),
-                                                      &parent_scope, true, force) {
+                                                      parent_scope, true, force) {
                             Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
                                 let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
                                                ty::Visibility::Public, derive.span, ExpnId::root())
@@ -502,7 +502,7 @@ impl<'a> Resolver<'a> {
                         ModuleOrUniformRoot::Module(root_module),
                         ident,
                         ns,
-                        None,
+                        parent_scope,
                         record_used,
                         path_span,
                     );
@@ -516,17 +516,16 @@ impl<'a> Resolver<'a> {
                     }
                 }
                 Scope::Module(module) => {
-                    let orig_current_module = mem::replace(&mut this.current_module, module);
+                    let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() };
                     let binding = this.resolve_ident_in_module_unadjusted_ext(
                         ModuleOrUniformRoot::Module(module),
                         ident,
                         ns,
-                        None,
+                        adjusted_parent_scope,
                         true,
                         record_used,
                         path_span,
                     );
-                    this.current_module = orig_current_module;
                     match binding {
                         Ok(binding) => {
                             let misc_flags = if ptr::eq(module, this.graph_root) {
@@ -588,6 +587,7 @@ impl<'a> Resolver<'a> {
                             ModuleOrUniformRoot::Module(prelude),
                             ident,
                             ns,
+                            parent_scope,
                             false,
                             path_span,
                         ) {
@@ -710,9 +710,7 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    pub fn finalize_current_module_macro_resolutions(&mut self) {
-        let module = self.current_module;
-
+    pub fn finalize_current_module_macro_resolutions(&mut self, module: Module<'a>) {
         let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
                                  initial_res: Option<Res>, res: Res| {
             if let Some(initial_res) = initial_res {
@@ -753,8 +751,9 @@ impl<'a> Resolver<'a> {
         for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions {
             // FIXME: Path resolution will ICE if segment IDs present.
             for seg in &mut path { seg.id = None; }
-            match self.resolve_path(&path, Some(MacroNS), &parent_scope,
-                                    true, path_span, CrateLint::No) {
+            match self.resolve_path(
+                &path, Some(MacroNS), &parent_scope, true, path_span, CrateLint::No
+            ) {
                 PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
                     let res = path_res.base_res();
                     check_consistency(self, &path, path_span, kind, initial_res, res);
@@ -887,10 +886,10 @@ impl<'a> Resolver<'a> {
         Lrc::new(result)
     }
 
-    pub fn define_macro(&mut self,
-                        item: &ast::Item,
-                        expansion: ExpnId,
-                        current_legacy_scope: &mut LegacyScope<'a>) {
+    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());
@@ -901,7 +900,7 @@ impl<'a> Resolver<'a> {
                     self.proc_macro_stubs.insert(item.id);
                     (self.dummy_ext(macro_kind), ident, span, false)
                 }
-                None => return,
+                None => return parent_scope.legacy,
             }
             _ => unreachable!(),
         };
@@ -909,7 +908,7 @@ impl<'a> Resolver<'a> {
         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, self.current_module);
+        self.local_macro_def_scopes.insert(item.id, parent_scope.module);
 
         if is_legacy {
             let ident = ident.modern();
@@ -921,11 +920,7 @@ impl<'a> Resolver<'a> {
                 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, self.current_module);
-            let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
-                parent_legacy_scope: *current_legacy_scope, binding, ident
-            });
-            *current_legacy_scope = LegacyScope::Binding(legacy_binding);
+            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;
@@ -935,13 +930,17 @@ impl<'a> Resolver<'a> {
                 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 = self.current_module;
-            let vis = self.resolve_visibility(&item.vis);
+            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 59438883d60..4611b813153 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -167,11 +167,12 @@ impl<'a> Resolver<'a> {
         module: ModuleOrUniformRoot<'a>,
         ident: Ident,
         ns: Namespace,
+        parent_scope: &ParentScope<'a>,
         record_used: bool,
         path_span: Span,
     ) -> Result<&'a NameBinding<'a>, Determinacy> {
         self.resolve_ident_in_module_unadjusted_ext(
-            module, ident, ns, None, false, record_used, path_span
+            module, ident, ns, parent_scope, false, record_used, path_span
         ).map_err(|(determinacy, _)| determinacy)
     }
 
@@ -182,7 +183,7 @@ impl<'a> Resolver<'a> {
         module: ModuleOrUniformRoot<'a>,
         ident: Ident,
         ns: Namespace,
-        parent_scope: Option<&ParentScope<'a>>,
+        parent_scope: &ParentScope<'a>,
         restricted_shadowing: bool,
         record_used: bool,
         path_span: Span,
@@ -191,9 +192,8 @@ impl<'a> Resolver<'a> {
             ModuleOrUniformRoot::Module(module) => module,
             ModuleOrUniformRoot::CrateRootAndExternPrelude => {
                 assert!(!restricted_shadowing);
-                let parent_scope = self.dummy_parent_scope();
                 let binding = self.early_resolve_ident_in_lexical_scope(
-                    ident, ScopeSet::AbsolutePath(ns), &parent_scope,
+                    ident, ScopeSet::AbsolutePath(ns), parent_scope,
                     record_used, record_used, path_span,
                 );
                 return binding.map_err(|determinacy| (determinacy, Weak::No));
@@ -213,9 +213,6 @@ impl<'a> Resolver<'a> {
             }
             ModuleOrUniformRoot::CurrentScope => {
                 assert!(!restricted_shadowing);
-                let parent_scope =
-                    parent_scope.expect("no parent scope for a single-segment import");
-
                 if ns == TypeNS {
                     if ident.name == kw::Crate ||
                         ident.name == kw::DollarCrate {
@@ -261,7 +258,8 @@ impl<'a> Resolver<'a> {
             }
             // `extern crate` are always usable for backwards compatibility, see issue #37020,
             // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
-            let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
+            let usable = this.is_accessible_from(binding.vis, parent_scope.module) ||
+                         binding.is_extern_crate();
             if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
         };
 
@@ -299,7 +297,7 @@ impl<'a> Resolver<'a> {
                         }
                     }
 
-                    if !self.is_accessible(binding.vis) &&
+                    if !self.is_accessible_from(binding.vis, parent_scope.module) &&
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
                        !(self.last_import_segment && binding.is_extern_crate()) {
                         self.privacy_errors.push(PrivacyError(path_span, ident, binding));
@@ -322,7 +320,7 @@ impl<'a> Resolver<'a> {
         // Check if one of single imports can still define the name,
         // if it can then our result is not determined and can be invalidated.
         for single_import in &resolution.single_imports {
-            if !self.is_accessible(single_import.vis.get()) {
+            if !self.is_accessible_from(single_import.vis.get(), parent_scope.module) {
                 continue;
             }
             let module = unwrap_or!(single_import.imported_module.get(),
@@ -331,7 +329,7 @@ impl<'a> Resolver<'a> {
                 SingleImport { source, .. } => source,
                 _ => unreachable!(),
             };
-            match self.resolve_ident_in_module(module, ident, ns, Some(&single_import.parent_scope),
+            match self.resolve_ident_in_module(module, ident, ns, &single_import.parent_scope,
                                                false, path_span) {
                 Err(Determined) => continue,
                 Ok(binding) if !self.is_accessible_from(
@@ -379,7 +377,7 @@ impl<'a> Resolver<'a> {
         // Check if one of glob imports can still define the name,
         // if it can then our "no resolution" result is not determined and can be invalidated.
         for glob_import in module.globs.borrow().iter() {
-            if !self.is_accessible(glob_import.vis.get()) {
+            if !self.is_accessible_from(glob_import.vis.get(), parent_scope.module) {
                 continue
             }
             let module = match glob_import.imported_module.get() {
@@ -387,9 +385,14 @@ impl<'a> Resolver<'a> {
                 Some(_) => continue,
                 None => return Err((Undetermined, Weak::Yes)),
             };
-            let (orig_current_module, mut ident) = (self.current_module, ident.modern());
+            let tmp_parent_scope;
+            let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.modern());
             match ident.span.glob_adjust(module.expansion, glob_import.span) {
-                Some(Some(def)) => self.current_module = self.macro_def_scope(def),
+                Some(Some(def)) => {
+                    tmp_parent_scope =
+                        ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() };
+                    adjusted_parent_scope = &tmp_parent_scope;
+                }
                 Some(None) => {}
                 None => continue,
             };
@@ -397,10 +400,10 @@ impl<'a> Resolver<'a> {
                 ModuleOrUniformRoot::Module(module),
                 ident,
                 ns,
+                adjusted_parent_scope,
                 false,
                 path_span,
             );
-            self.current_module = orig_current_module;
 
             match result {
                 Err(Determined) => continue,
@@ -798,11 +801,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
     /// Attempts to resolve the given import, returning true if its resolution is determined.
     /// If successful, the resolved bindings are written into the module.
     fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
-        debug!("(resolving import for module) resolving import `{}::...` in `{}`",
-               Segment::names_to_string(&directive.module_path),
-               module_to_string(self.current_module).unwrap_or_else(|| "???".to_string()));
-
-        self.current_module = directive.parent_scope.module;
+        debug!(
+            "(resolving import for module) resolving import `{}::...` in `{}`",
+            Segment::names_to_string(&directive.module_path),
+            module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()),
+        );
 
         let module = if let Some(module) = directive.imported_module.get() {
             module
@@ -847,7 +850,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 // not define any names while resolving its module path.
                 let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
                 let binding = this.resolve_ident_in_module(
-                    module, source, ns, Some(&directive.parent_scope), false, directive.span
+                    module, source, ns, &directive.parent_scope, false, directive.span
                 );
                 directive.vis.set(orig_vis);
 
@@ -892,8 +895,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         &mut self,
         directive: &'b ImportDirective<'b>
     ) -> Option<UnresolvedImportError> {
-        self.current_module = directive.parent_scope.module;
-
         let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
         let prev_ambiguity_errors_len = self.ambiguity_errors.len();
         let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope,
@@ -1019,7 +1020,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
             let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
             let binding = this.resolve_ident_in_module(
-                module, ident, ns, Some(&directive.parent_scope), true, directive.span
+                module, ident, ns, &directive.parent_scope, true, directive.span
             );
             this.last_import_segment = orig_last_import_segment;
             this.blacklisted_binding = orig_blacklisted_binding;
@@ -1070,7 +1071,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             let mut all_ns_failed = true;
             self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
                 let binding = this.resolve_ident_in_module(
-                    module, ident, ns, Some(&directive.parent_scope), true, directive.span
+                    module, ident, ns, &directive.parent_scope, true, directive.span
                 );
                 if binding.is_ok() {
                     all_ns_failed = false;
@@ -1340,7 +1341,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         for ((mut ident, ns), binding) in bindings {
             let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
                 Some(Some(def)) => self.macro_def_scope(def),
-                Some(None) => self.current_module,
+                Some(None) => directive.parent_scope.module,
                 None => continue,
             };
             if self.is_accessible_from(binding.pseudo_vis(), scope) {
diff --git a/src/test/ui/hygiene/privacy-early.rs b/src/test/ui/hygiene/privacy-early.rs
new file mode 100644
index 00000000000..58fc74d65a5
--- /dev/null
+++ b/src/test/ui/hygiene/privacy-early.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![feature(decl_macro)]
+
+mod foo {
+    fn f() {}
+    macro f() {}
+
+    pub macro m() {
+        use f as g; //~ ERROR `f` is private, and cannot be re-exported
+        f!();
+    }
+}
+
+fn main() {
+    foo::m!();
+}
diff --git a/src/test/ui/hygiene/privacy-early.stderr b/src/test/ui/hygiene/privacy-early.stderr
new file mode 100644
index 00000000000..60e50e05fc3
--- /dev/null
+++ b/src/test/ui/hygiene/privacy-early.stderr
@@ -0,0 +1,21 @@
+error[E0364]: `f` is private, and cannot be re-exported
+  --> $DIR/privacy-early.rs:10:13
+   |
+LL |         use f as g;
+   |             ^^^^^^
+...
+LL |     foo::m!();
+   |     ---------- in this macro invocation
+   |
+note: consider marking `f` as `pub` in the imported module
+  --> $DIR/privacy-early.rs:10:13
+   |
+LL |         use f as g;
+   |             ^^^^^^
+...
+LL |     foo::m!();
+   |     ---------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0364`.
diff --git a/src/test/ui/resolve/resolve-bad-visibility.rs b/src/test/ui/resolve/resolve-bad-visibility.rs
index d86c300c93f..7d48bb97b10 100644
--- a/src/test/ui/resolve/resolve-bad-visibility.rs
+++ b/src/test/ui/resolve/resolve-bad-visibility.rs
@@ -4,8 +4,8 @@ trait Tr {}
 pub(in E) struct S; //~ ERROR expected module, found enum `E`
 pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr`
 pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
-pub(in nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root
-pub(in too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root
+pub(in nonexistent) struct G; //~ ERROR failed to resolve
+pub(in too_soon) struct H; //~ ERROR failed to resolve
 
 // Visibilities are resolved eagerly without waiting for modules becoming fully populated.
 // Visibilities can only use ancestor modules legally which are always available in time,
diff --git a/src/test/ui/resolve/resolve-bad-visibility.stderr b/src/test/ui/resolve/resolve-bad-visibility.stderr
index b8004a48a67..a133b02335c 100644
--- a/src/test/ui/resolve/resolve-bad-visibility.stderr
+++ b/src/test/ui/resolve/resolve-bad-visibility.stderr
@@ -1,9 +1,3 @@
-error: visibilities can only be restricted to ancestor modules
-  --> $DIR/resolve-bad-visibility.rs:6:8
-   |
-LL | pub(in std::vec) struct F;
-   |        ^^^^^^^^
-
 error[E0577]: expected module, found enum `E`
   --> $DIR/resolve-bad-visibility.rs:4:8
    |
@@ -16,17 +10,24 @@ error[E0577]: expected module, found trait `Tr`
 LL | pub(in Tr) struct Z;
    |        ^^ not a module
 
-error[E0578]: cannot find module `nonexistent` in the crate root
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/resolve-bad-visibility.rs:6:8
+   |
+LL | pub(in std::vec) struct F;
+   |        ^^^^^^^^
+
+error[E0433]: failed to resolve: maybe a missing `extern crate nonexistent;`?
   --> $DIR/resolve-bad-visibility.rs:7:8
    |
 LL | pub(in nonexistent) struct G;
-   |        ^^^^^^^^^^^ not found in the crate root
+   |        ^^^^^^^^^^^ maybe a missing `extern crate nonexistent;`?
 
-error[E0578]: cannot find module `too_soon` in the crate root
+error[E0433]: failed to resolve: maybe a missing `extern crate too_soon;`?
   --> $DIR/resolve-bad-visibility.rs:8:8
    |
 LL | pub(in too_soon) struct H;
-   |        ^^^^^^^^ not found in the crate root
+   |        ^^^^^^^^ maybe a missing `extern crate too_soon;`?
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs
new file mode 100644
index 00000000000..595eaf440c9
--- /dev/null
+++ b/src/test/ui/resolve/visibility-indeterminate.rs
@@ -0,0 +1,5 @@
+// edition:2018
+
+foo!(); //~ ERROR cannot find macro `foo!` in this scope
+
+pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr
new file mode 100644
index 00000000000..a259c8090b3
--- /dev/null
+++ b/src/test/ui/resolve/visibility-indeterminate.stderr
@@ -0,0 +1,19 @@
+error[E0578]: cannot determine resolution for the visibility
+  --> $DIR/visibility-indeterminate.rs:5:8
+   |
+LL | pub(in ::bar) struct Baz {}
+   |        ^^^^^
+
+error: cannot find macro `foo!` in this scope
+  --> $DIR/visibility-indeterminate.rs:3:1
+   |
+LL | foo!();
+   | ^^^
+
+error[E0601]: `main` function not found in crate `visibility_indeterminate`
+   |
+   = note: consider adding a `main` function to `$DIR/visibility-indeterminate.rs`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr
index cdbede3c197..c2f0711b0c8 100644
--- a/src/test/ui/span/visibility-ty-params.stderr
+++ b/src/test/ui/span/visibility-ty-params.stderr
@@ -4,19 +4,17 @@ error: unexpected generic arguments in path
 LL | m!{ S<u8> }
    |     ^^^^^
 
+error[E0577]: expected module, found struct `S`
+  --> $DIR/visibility-ty-params.rs:6:5
+   |
+LL | m!{ S<u8> }
+   |     ^^^^^ not a module
+
 error: unexpected generic arguments in path
   --> $DIR/visibility-ty-params.rs:10:9
    |
 LL |     m!{ m<> }
    |         ^^^
 
-error[E0577]: expected module, found struct `S`
-  --> $DIR/visibility-ty-params.rs:6:5
-   |
-LL | m!{ S<u8> }
-   |     -^^^^
-   |     |
-   |     help: a module with a similar name exists: `m`
-
 error: aborting due to 3 previous errors