about summary refs log tree commit diff
diff options
context:
space:
mode:
-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