diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6485acf4ed2cc..f3fe53444bfe9 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1484,15 +1484,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`,
     /// or by opting into an edition after 2015.
     pub fn two_phase_borrows(self) -> bool {
-        if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows {
-            return true;
-        }
-
-        match self.sess.edition() {
-            Edition::Edition2015 => false,
-            Edition::Edition2018 => true,
-            _ => true,
-        }
+        self.sess.rust_2018() || self.features().nll ||
+        self.sess.opts.debugging_opts.two_phase_borrows
     }
 
     /// What mode(s) of borrowck should we run? AST? MIR? both?
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 7153c729d1542..6d92890fc08ad 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -14,7 +14,6 @@ use ty::{self, DefIdTree, Ty, TyCtxt};
 use middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::{keywords, LocalInternedString, Symbol};
-use syntax_pos::edition::Edition;
 
 use std::cell::Cell;
 use std::fmt::Debug;
@@ -140,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         debug!("push_krate_path: name={:?}", name);
                         buffer.push(&name);
                     }
-                } else if self.sess.edition() == Edition::Edition2018 && !pushed_prelude_crate {
+                } else if self.sess.rust_2018() && !pushed_prelude_crate {
                     SHOULD_PREFIX_WITH_CRATE.with(|flag| {
                         // We only add the `crate::` keyword where appropriate. In particular,
                         // when we've not previously pushed a prelude crate to this path.
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index b3a70c79df144..715b788ea8a9d 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -132,17 +132,21 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         // so prefixes are prepended with crate root segment if necessary.
         // The root is prepended lazily, when the first non-empty prefix or terminating glob
         // appears, so imports in braced groups can have roots prepended independently.
+        // 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't
+        // get crate root prepended, but get special treatment during in-scope resolution instead.
         let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
-        let crate_root = if !self.session.rust_2018() &&
-            prefix_iter.peek().map_or(is_glob, |seg| !seg.ident.is_path_segment_keyword())
-        {
-            Some(Segment::from_ident(Ident::new(
-                keywords::CrateRoot.name(),
-                use_tree.prefix.span.shrink_to_lo(),
-            )))
-        } else {
-            None
-        };
+        let crate_root = match prefix_iter.peek() {
+            Some(seg) if !seg.ident.is_path_segment_keyword() &&
+                         seg.ident.span.rust_2015() && self.session.rust_2015() => {
+                Some(seg.ident.span.ctxt())
+            }
+            None if is_glob && use_tree.span.rust_2015() => {
+                Some(use_tree.span.ctxt())
+            }
+            _ => None,
+        }.map(|ctxt| Segment::from_ident(Ident::new(
+            keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt)
+        )));
 
         let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
         debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 263d23d133e1c..e2a6303f57944 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -33,7 +33,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
             (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() &&
                                       !snd.ident.is_path_segment_keyword() => {}
             // `ident::...` on 2018
-            (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => {
+            (Some(fst), _) if fst.ident.span.rust_2018() &&
+                              !fst.ident.is_path_segment_keyword() => {
                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
                 path.insert(0, Segment::from_ident(keywords::Invalid.ident()));
             }
@@ -141,7 +142,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
     ) -> Option<(Vec<Segment>, Option<String>)> {
-        if !self.session.rust_2018() {
+        if path[1].ident.span.rust_2015() {
             return None;
         }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 26fab593e4cdd..70324f6a1498b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -13,6 +13,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
+#![feature(label_break_value)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
@@ -101,6 +102,13 @@ enum Weak {
     No,
 }
 
+enum ScopeSet {
+    Import(Namespace),
+    AbsolutePath(Namespace),
+    Macro(MacroKind),
+    Module,
+}
+
 /// A free importable items suggested in case of resolution failure.
 struct ImportSuggestion {
     path: Path,
@@ -996,31 +1004,33 @@ impl<'a> LexicalScopeBinding<'a> {
     }
 }
 
-
-#[derive(Clone, Copy, PartialEq, Debug)]
-enum UniformRootKind {
-    CurrentScope,
-    ExternPrelude,
-}
-
 #[derive(Copy, Clone, Debug)]
 enum ModuleOrUniformRoot<'a> {
     /// Regular module.
     Module(Module<'a>),
 
-    /// This "virtual module" denotes either resolution in extern prelude
-    /// for paths starting with `::` on 2018 edition or `extern::`,
-    /// or resolution in current scope for single-segment imports.
-    UniformRoot(UniformRootKind),
+    /// Virtual module that denotes resolution in crate root with fallback to extern prelude.
+    CrateRootAndExternPrelude,
+
+    /// Virtual module that denotes resolution in extern prelude.
+    /// Used for paths starting with `::` on 2018 edition or `extern::`.
+    ExternPrelude,
+
+    /// Virtual module that denotes resolution in current scope.
+    /// Used only for resolving single-segment imports. The reason it exists is that import paths
+    /// are always split into two parts, the first of which should be some kind of module.
+    CurrentScope,
 }
 
 impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
     fn eq(&self, other: &Self) -> bool {
         match (*self, *other) {
-            (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
-                ptr::eq(lhs, rhs),
-            (ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) =>
-                lhs == rhs,
+            (ModuleOrUniformRoot::Module(lhs),
+             ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs),
+            (ModuleOrUniformRoot::CrateRootAndExternPrelude,
+             ModuleOrUniformRoot::CrateRootAndExternPrelude) |
+            (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
+            (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
             _ => false,
         }
     }
@@ -1239,6 +1249,7 @@ struct UseError<'a> {
 #[derive(Clone, Copy, PartialEq, Debug)]
 enum AmbiguityKind {
     Import,
+    AbsolutePath,
     BuiltinAttr,
     DeriveHelper,
     LegacyHelperVsPrelude,
@@ -1254,6 +1265,8 @@ impl AmbiguityKind {
         match self {
             AmbiguityKind::Import =>
                 "name vs any other name during import resolution",
+            AmbiguityKind::AbsolutePath =>
+                "name in the crate root vs extern crate during absolute path resolution",
             AmbiguityKind::BuiltinAttr =>
                 "built-in attribute vs any other name",
             AmbiguityKind::DeriveHelper =>
@@ -1279,6 +1292,7 @@ impl AmbiguityKind {
 /// Miscellaneous bits of metadata for better ambiguity error reporting.
 #[derive(Clone, Copy, PartialEq)]
 enum AmbiguityErrorMisc {
+    SuggestCrate,
     SuggestSelf,
     FromPrelude,
     None,
@@ -1762,8 +1776,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 error_callback(self, span, ResolutionError::FailedToResolve(msg));
                 Def::Err
             }
-            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
-            PathResult::Indeterminate => unreachable!(),
+            PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
                 error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 Def::Err
@@ -2196,28 +2209,46 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     fn resolve_ident_in_module(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
-        mut ident: Ident,
+        ident: Ident,
         ns: Namespace,
         parent_scope: Option<&ParentScope<'a>>,
         record_used: bool,
         path_span: Span
     ) -> Result<&'a NameBinding<'a>, Determinacy> {
-        ident.span = ident.span.modern();
+        self.resolve_ident_in_module_ext(
+            module, ident, ns, parent_scope, record_used, path_span
+        ).map_err(|(determinacy, _)| determinacy)
+    }
+
+    fn resolve_ident_in_module_ext(
+        &mut self,
+        module: ModuleOrUniformRoot<'a>,
+        mut ident: Ident,
+        ns: Namespace,
+        parent_scope: Option<&ParentScope<'a>>,
+        record_used: bool,
+        path_span: Span
+    ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
         let orig_current_module = self.current_module;
         match module {
             ModuleOrUniformRoot::Module(module) => {
+                ident.span = ident.span.modern();
                 if let Some(def) = ident.span.adjust(module.expansion) {
                     self.current_module = self.macro_def_scope(def);
                 }
             }
-            ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
+            ModuleOrUniformRoot::ExternPrelude => {
+                ident.span = ident.span.modern();
                 ident.span.adjust(Mark::root());
             }
-            _ => {}
+            ModuleOrUniformRoot::CrateRootAndExternPrelude |
+            ModuleOrUniformRoot::CurrentScope => {
+                // No adjustments
+            }
         }
         let result = self.resolve_ident_in_module_unadjusted_ext(
             module, ident, ns, parent_scope, false, record_used, path_span,
-        ).map_err(|(determinacy, _)| determinacy);
+        );
         self.current_module = orig_current_module;
         result
     }
@@ -2359,14 +2390,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     }
 
     fn future_proof_import(&mut self, use_tree: &ast::UseTree) {
-        if !self.session.rust_2018() {
-            return;
-        }
-
         let segments = &use_tree.prefix.segments;
         if !segments.is_empty() {
             let ident = segments[0].ident;
-            if ident.is_path_segment_keyword() {
+            if ident.is_path_segment_keyword() || ident.span.rust_2015() {
                 return;
             }
 
@@ -3186,10 +3213,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
             // Try to lookup the name in more relaxed fashion for better error reporting.
             let ident = path.last().unwrap().ident;
-            let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
+            let candidates = this.lookup_import_candidates(ident, ns, is_expected);
             if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
                 let enum_candidates =
-                    this.lookup_import_candidates(ident.name, ns, is_enum_variant);
+                    this.lookup_import_candidates(ident, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
                     .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
                 enum_candidates.sort();
@@ -3655,8 +3682,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 err_path_resolution()
             }
-            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
-            PathResult::Failed(..) => return None,
+            PathResult::Module(..) | PathResult::Failed(..) => return None,
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
@@ -3774,9 +3800,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                         continue;
                     }
                     if name == keywords::Extern.name() ||
-                       name == keywords::CrateRoot.name() && self.session.rust_2018() {
-                        module =
-                            Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude));
+                       name == keywords::CrateRoot.name() && ident.span.rust_2018() {
+                        module = Some(ModuleOrUniformRoot::ExternPrelude);
+                        continue;
+                    }
+                    if name == keywords::CrateRoot.name() &&
+                       ident.span.rust_2015() && self.session.rust_2018() {
+                        // `::a::b` from 2015 macro on 2018 global edition
+                        module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
                         continue;
                     }
                     if name == keywords::CrateRoot.name() ||
@@ -3809,9 +3840,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span)
             } else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
-                self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
-                                                          parent_scope, record_used, record_used,
-                                                          path_span)
+                let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module };
+                self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used,
+                                                          record_used, path_span)
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3877,7 +3908,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     let msg = if module_def == self.graph_root.def() {
                         let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
                         let mut candidates =
-                            self.lookup_import_candidates(name, TypeNS, is_mod);
+                            self.lookup_import_candidates(ident, TypeNS, is_mod);
                         candidates.sort_by_cached_key(|c| {
                             (c.path.segments.len(), c.path.to_string())
                         });
@@ -3900,8 +3931,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         PathResult::Module(match module {
             Some(module) => module,
-            None if path.is_empty() =>
-                ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope),
+            None if path.is_empty() => ModuleOrUniformRoot::CurrentScope,
             _ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
         })
     }
@@ -3913,11 +3943,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         path_span: Span,
         second_binding: Option<&NameBinding>,
     ) {
-        // In the 2018 edition this lint is a hard error, so nothing to do
-        if self.session.rust_2018() {
-            return
-        }
-
         let (diag_id, diag_span) = match crate_lint {
             CrateLint::No => return,
             CrateLint::SimplePath(id) => (id, path_span),
@@ -3926,8 +3951,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         };
 
         let first_name = match path.get(0) {
-            Some(ident) => ident.ident.name,
-            None => return,
+            // In the 2018 edition this lint is a hard error, so nothing to do
+            Some(seg) if seg.ident.span.rust_2015() => seg.ident.name,
+            _ => return,
         };
 
         // We're only interested in `use` paths which should start with
@@ -4509,7 +4535,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     }
 
     fn lookup_import_candidates_from_module<FilterFn>(&mut self,
-                                          lookup_name: Name,
+                                          lookup_ident: Ident,
                                           namespace: Namespace,
                                           start_module: &'a ModuleData<'a>,
                                           crate_name: Ident,
@@ -4536,11 +4562,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 if !name_binding.is_importable() { return; }
 
                 // collect results based on the filter function
-                if ident.name == lookup_name && ns == namespace {
+                if ident.name == lookup_ident.name && ns == namespace {
                     if filter_fn(name_binding.def()) {
                         // create the path
                         let mut segms = path_segments.clone();
-                        if self.session.rust_2018() {
+                        if lookup_ident.span.rust_2018() {
                             // crate-local absolute paths start with `crate::` in edition 2018
                             // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
                             segms.insert(
@@ -4574,7 +4600,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
                     let is_extern_crate_that_also_appears_in_prelude =
                         name_binding.is_extern_crate() &&
-                        self.session.rust_2018();
+                        lookup_ident.span.rust_2018();
 
                     let is_visible_to_user =
                         !in_module_is_extern || name_binding.vis == ty::Visibility::Public;
@@ -4601,16 +4627,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     /// NOTE: The method does not look into imports, but this is not a problem,
     /// since we report the definitions (thus, the de-aliased imports).
     fn lookup_import_candidates<FilterFn>(&mut self,
-                                          lookup_name: Name,
+                                          lookup_ident: Ident,
                                           namespace: Namespace,
                                           filter_fn: FilterFn)
                                           -> Vec<ImportSuggestion>
         where FilterFn: Fn(Def) -> bool
     {
         let mut suggestions = self.lookup_import_candidates_from_module(
-            lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
+            lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
 
-        if self.session.rust_2018() {
+        if lookup_ident.span.rust_2018() {
             let extern_prelude_names = self.extern_prelude.clone();
             for (ident, _) in extern_prelude_names.into_iter() {
                 if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
@@ -4622,7 +4648,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     self.populate_module_if_necessary(&crate_root);
 
                     suggestions.extend(self.lookup_import_candidates_from_module(
-                        lookup_name, namespace, crate_root, ident, &filter_fn));
+                        lookup_ident, namespace, crate_root, ident, &filter_fn));
                 }
             }
         }
@@ -4714,19 +4740,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
                 // For visibilities we are not ready to provide correct implementation of "uniform
                 // paths" right now, so on 2018 edition we only allow module-relative paths for now.
-                let first_ident = path.segments[0].ident;
-                if self.session.rust_2018() && !first_ident.is_path_segment_keyword() {
+                // On 2015 edition visibilities are resolved as crate-relative by default,
+                // so we are prepending a root segment if necessary.
+                let ident = path.segments.get(0).expect("empty path in visibility").ident;
+                let crate_root = if ident.is_path_segment_keyword() {
+                    None
+                } else if ident.span.rust_2018() {
                     let msg = "relative paths are not supported in visibilities on 2018 edition";
-                    self.session.struct_span_err(first_ident.span, msg)
+                    self.session.struct_span_err(ident.span, msg)
                                 .span_suggestion(path.span, "try", format!("crate::{}", path))
                                 .emit();
                     return ty::Visibility::Public;
-                }
-                // On 2015 visibilities are resolved as crate-relative by default,
-                // add starting root segment if necessary.
-                let segments = path.make_root().iter().chain(path.segments.iter())
-                    .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) })
-                    .collect::<Vec<_>>();
+                } else {
+                    let ctxt = ident.span.ctxt();
+                    Some(Segment::from_ident(Ident::new(
+                        keywords::CrateRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt)
+                    )))
+                };
+
+                let segments = crate_root.into_iter()
+                    .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
                 let def = self.smart_resolve_path_fragment(
                     id,
                     None,
@@ -4839,13 +4872,22 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 help_msgs.push(format!("consider adding an explicit import of \
                                         `{ident}` to disambiguate", ident = ident))
             }
-            if b.is_extern_crate() && self.session.rust_2018() {
-                help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously",
-                                       ident = ident, thing = b.descr()))
-            }
-            if misc == AmbiguityErrorMisc::SuggestSelf {
-                help_msgs.push(format!("use `self::{ident}` to refer to this {thing} unambiguously",
-                                       ident = ident, thing = b.descr()))
+            if b.is_extern_crate() && ident.span.rust_2018() {
+                help_msgs.push(format!(
+                    "use `::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident, thing = b.descr(),
+                ))
+            }
+            if misc == AmbiguityErrorMisc::SuggestCrate {
+                help_msgs.push(format!(
+                    "use `crate::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident, thing = b.descr(),
+                ))
+            } else if misc == AmbiguityErrorMisc::SuggestSelf {
+                help_msgs.push(format!(
+                    "use `self::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident, thing = b.descr(),
+                ))
             }
 
             if b.span.is_dummy() {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index df73befa324f0..5db3efee9f6a1 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
-use {CrateLint, Resolver, ResolutionError, Weak};
+use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
 use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
 use {is_known_tool, resolve_error};
 use ModuleOrUniformRoot;
-use Namespace::{self, *};
+use Namespace::*;
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
@@ -42,7 +42,7 @@ use syntax_pos::{Span, DUMMY_SP};
 use errors::Applicability;
 
 use std::cell::Cell;
-use std::mem;
+use std::{mem, ptr};
 use rustc_data_structures::sync::Lrc;
 
 #[derive(Clone, Debug)]
@@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
             def
         } else {
             let binding = self.early_resolve_ident_in_lexical_scope(
-                path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span
+                path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
             );
             match binding {
                 Ok(..) => {}
@@ -526,10 +526,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
     // `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
     crate fn early_resolve_ident_in_lexical_scope(
         &mut self,
-        mut ident: Ident,
-        ns: Namespace,
-        macro_kind: Option<MacroKind>,
-        is_import: bool,
+        orig_ident: Ident,
+        scope_set: ScopeSet,
         parent_scope: &ParentScope<'a>,
         record_used: bool,
         force: bool,
@@ -582,6 +580,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         enum WhereToResolve<'a> {
             DeriveHelpers,
             MacroRules(LegacyScope<'a>),
+            CrateRoot,
             Module(Module<'a>),
             MacroUsePrelude,
             BuiltinMacros,
@@ -595,17 +594,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
 
         bitflags! {
             struct Flags: u8 {
-                const MACRO_RULES       = 1 << 0;
-                const MODULE            = 1 << 1;
-                const PRELUDE           = 1 << 2;
-                const MISC_SUGGEST_SELF = 1 << 3;
-                const MISC_FROM_PRELUDE = 1 << 4;
+                const MACRO_RULES        = 1 << 0;
+                const MODULE             = 1 << 1;
+                const PRELUDE            = 1 << 2;
+                const MISC_SUGGEST_CRATE = 1 << 3;
+                const MISC_SUGGEST_SELF  = 1 << 4;
+                const MISC_FROM_PRELUDE  = 1 << 5;
             }
         }
 
         assert!(force || !record_used); // `record_used` implies `force`
-        assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
-        ident = ident.modern();
+        let mut ident = orig_ident.modern();
 
         // Make sure `self`, `super` etc produce an error when passed to here.
         if ident.is_path_segment_keyword() {
@@ -626,10 +625,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let mut innermost_result: Option<(&NameBinding, Flags)> = None;
 
         // Go through all the scopes and try to resolve the name.
-        let mut where_to_resolve = if ns == MacroNS {
-            WhereToResolve::DeriveHelpers
-        } else {
-            WhereToResolve::Module(parent_scope.module)
+        let rust_2015 = orig_ident.span.rust_2015();
+        let (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
+            ScopeSet::Import(ns) => (ns, None, true, false),
+            ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
+            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
+            ScopeSet::Module => (TypeNS, None, false, false),
+        };
+        let mut where_to_resolve = match ns {
+            _ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot,
+            TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
+            MacroNS => WhereToResolve::DeriveHelpers,
         };
         let mut use_prelude = !parent_scope.module.no_implicit_prelude;
         let mut determinacy = Determinacy::Determined;
@@ -667,6 +673,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                         Err(Determinacy::Undetermined),
                     _ => Err(Determinacy::Determined),
                 }
+                WhereToResolve::CrateRoot => {
+                    let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
+                    let root_module = self.resolve_crate_root(root_ident);
+                    let binding = self.resolve_ident_in_module_ext(
+                        ModuleOrUniformRoot::Module(root_module),
+                        orig_ident,
+                        ns,
+                        None,
+                        record_used,
+                        path_span,
+                    );
+                    match binding {
+                        Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
+                        Err((Determinacy::Undetermined, Weak::No)) =>
+                            return Err(Determinacy::determined(force)),
+                        Err((Determinacy::Undetermined, Weak::Yes)) =>
+                            Err(Determinacy::Undetermined),
+                        Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
+                    }
+                }
                 WhereToResolve::Module(module) => {
                     let orig_current_module = mem::replace(&mut self.current_module, module);
                     let binding = self.resolve_ident_in_module_unadjusted_ext(
@@ -681,7 +707,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     self.current_module = orig_current_module;
                     match binding {
                         Ok(binding) => {
-                            let misc_flags = if module.is_normal() {
+                            let misc_flags = if ptr::eq(module, self.graph_root) {
+                                Flags::MISC_SUGGEST_CRATE
+                            } else if module.is_normal() {
                                 Flags::MISC_SUGGEST_SELF
                             } else {
                                 Flags::empty()
@@ -696,7 +724,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                 }
                 WhereToResolve::MacroUsePrelude => {
-                    if use_prelude || self.session.rust_2015() {
+                    if use_prelude || rust_2015 {
                         match self.macro_use_prelude.get(&ident.name).cloned() {
                             Some(binding) =>
                                 Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
@@ -725,7 +753,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                 }
                 WhereToResolve::LegacyPluginHelpers => {
-                    if (use_prelude || self.session.rust_2015()) &&
+                    if (use_prelude || rust_2015) &&
                        self.session.plugin_attributes.borrow().iter()
                                                      .any(|(name, _)| ident.name == &**name) {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
@@ -737,7 +765,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                 }
                 WhereToResolve::ExternPrelude => {
-                    if use_prelude {
+                    if use_prelude || is_absolute_path {
                         match self.extern_prelude_get(ident, !record_used) {
                             Some(binding) => Ok((binding, Flags::PRELUDE)),
                             None => Err(Determinacy::determined(
@@ -803,6 +831,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
 
                             let ambiguity_error_kind = if is_import {
                                 Some(AmbiguityKind::Import)
+                            } else if is_absolute_path {
+                                Some(AmbiguityKind::AbsolutePath)
                             } else if innermost_def == builtin || def == builtin {
                                 Some(AmbiguityKind::BuiltinAttr)
                             } else if innermost_def == derive_helper || def == derive_helper {
@@ -815,7 +845,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                             } else if innermost_flags.contains(Flags::MACRO_RULES) &&
                                       flags.contains(Flags::MODULE) &&
                                       !self.disambiguate_legacy_vs_modern(innermost_binding,
-                                                                          binding) {
+                                                                          binding) ||
+                                      flags.contains(Flags::MACRO_RULES) &&
+                                      innermost_flags.contains(Flags::MODULE) &&
+                                      !self.disambiguate_legacy_vs_modern(binding,
+                                                                          innermost_binding) {
                                 Some(AmbiguityKind::LegacyVsModern)
                             } else if innermost_binding.is_glob_import() {
                                 Some(AmbiguityKind::GlobVsOuter)
@@ -826,7 +860,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                                 None
                             };
                             if let Some(kind) = ambiguity_error_kind {
-                                let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_SELF) {
+                                let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_CRATE) {
+                                    AmbiguityErrorMisc::SuggestCrate
+                                } else if f.contains(Flags::MISC_SUGGEST_SELF) {
                                     AmbiguityErrorMisc::SuggestSelf
                                 } else if f.contains(Flags::MISC_FROM_PRELUDE) {
                                     AmbiguityErrorMisc::FromPrelude
@@ -835,7 +871,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                                 };
                                 self.ambiguity_errors.push(AmbiguityError {
                                     kind,
-                                    ident,
+                                    ident: orig_ident,
                                     b1: innermost_binding,
                                     b2: binding,
                                     misc1: misc(innermost_flags),
@@ -866,6 +902,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
                     LegacyScope::Uninitialized => unreachable!(),
                 }
+                WhereToResolve::CrateRoot if is_import => match ns {
+                    TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
+                    MacroNS => WhereToResolve::DeriveHelpers,
+                }
+                WhereToResolve::CrateRoot if is_absolute_path => match ns {
+                    TypeNS => {
+                        ident.span.adjust(Mark::root());
+                        WhereToResolve::ExternPrelude
+                    }
+                    ValueNS | MacroNS => break,
+                }
+                WhereToResolve::CrateRoot => unreachable!(),
                 WhereToResolve::Module(module) => {
                     match self.hygienic_lexical_parent(module, &mut ident.span) {
                         Some(parent_module) => WhereToResolve::Module(parent_module),
@@ -883,6 +931,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                 WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
                 WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
                 WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
+                WhereToResolve::ExternPrelude if is_absolute_path => break,
                 WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
                 WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
                 WhereToResolve::StdLibPrelude => match ns {
@@ -898,30 +947,43 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
 
         // The first found solution was the only one, return it.
         if let Some((binding, flags)) = innermost_result {
-            if is_import && !self.session.features_untracked().uniform_paths {
-                // We get to here only if there's no ambiguity, in ambiguous cases an error will
-                // be reported anyway, so there's no reason to report an additional feature error.
-                // The `binding` can actually be introduced by something other than `--extern`,
-                // but its `Def` should coincide with a crate passed with `--extern`
-                // (otherwise there would be ambiguity) and we can skip feature error in this case.
-                if ns != TypeNS || !use_prelude ||
-                   self.extern_prelude_get(ident, true).is_none() {
-                    let msg = "imports can only refer to extern crate names \
-                               passed with `--extern` on stable channel";
-                    let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
-                                              ident.span, GateIssue::Language, msg);
-
-                    let what = self.binding_description(binding, ident,
-                                                        flags.contains(Flags::MISC_FROM_PRELUDE));
-                    let note_msg = format!("this import refers to {what}", what = what);
-                    if binding.span.is_dummy() {
-                        err.note(&note_msg);
-                    } else {
-                        err.span_note(binding.span, &note_msg);
-                        err.span_label(binding.span, "not an extern crate passed with `--extern`");
+            // We get to here only if there's no ambiguity, in ambiguous cases an error will
+            // be reported anyway, so there's no reason to report an additional feature error.
+            // The `binding` can actually be introduced by something other than `--extern`,
+            // but its `Def` should coincide with a crate passed with `--extern`
+            // (otherwise there would be ambiguity) and we can skip feature error in this case.
+            'ok: {
+                if !is_import || self.session.features_untracked().uniform_paths {
+                    break 'ok;
+                }
+                if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
+                    break 'ok;
+                }
+                if rust_2015 {
+                    let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
+                    let root_module = self.resolve_crate_root(root_ident);
+                    if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
+                                                        orig_ident, ns, None, false, path_span)
+                                                        .is_ok() {
+                        break 'ok;
                     }
-                    err.emit();
                 }
+
+                let msg = "imports can only refer to extern crate names \
+                           passed with `--extern` on stable channel";
+                let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
+                                          ident.span, GateIssue::Language, msg);
+
+                let what = self.binding_description(binding, ident,
+                                                    flags.contains(Flags::MISC_FROM_PRELUDE));
+                let note_msg = format!("this import refers to {what}", what = what);
+                if binding.span.is_dummy() {
+                    err.note(&note_msg);
+                } else {
+                    err.span_note(binding.span, &note_msg);
+                    err.span_label(binding.span, "not an extern crate passed with `--extern`");
+                }
+                err.emit();
             }
 
             return Ok(binding);
@@ -998,7 +1060,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let macro_resolutions =
             mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
         for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
-            match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false,
+            match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
                                                             &parent_scope, true, true, ident.span) {
                 Ok(binding) => {
                     let initial_def = initial_binding.map(|initial_binding| {
@@ -1024,7 +1086,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
         for (ident, parent_scope) in builtin_attrs {
             let _ = self.early_resolve_ident_in_lexical_scope(
-                ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
+                ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
             );
         }
     }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index d860bafce1329..88551f6566a25 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -11,7 +11,7 @@
 use self::ImportDirectiveSubclass::*;
 
 use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
-use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak};
+use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
 use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use {Resolver, Segment};
@@ -162,46 +162,51 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
     ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
         let module = match module {
             ModuleOrUniformRoot::Module(module) => module,
-            ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => {
+            ModuleOrUniformRoot::CrateRootAndExternPrelude => {
                 assert!(!restricted_shadowing);
-                match uniform_root_kind {
-                    UniformRootKind::ExternPrelude => {
-                        return if let Some(binding) =
-                                self.extern_prelude_get(ident, !record_used) {
-                            Ok(binding)
-                        } else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
-                            // Macro-expanded `extern crate` items can add names to extern prelude.
-                            Err((Undetermined, Weak::No))
-                        } else {
-                            Err((Determined, Weak::No))
-                        }
-                    }
-                    UniformRootKind::CurrentScope => {
-                        let parent_scope =
-                            parent_scope.expect("no parent scope for a single-segment import");
-
-                        if ns == TypeNS {
-                            if ident.name == keywords::Crate.name() ||
-                               ident.name == keywords::DollarCrate.name() {
-                                let module = self.resolve_crate_root(ident);
-                                let binding = (module, ty::Visibility::Public,
-                                               module.span, Mark::root())
-                                               .to_name_binding(self.arenas);
-                                return Ok(binding);
-                            } else if ident.name == keywords::Super.name() ||
-                                      ident.name == keywords::SelfValue.name() {
-                                // FIXME: Implement these with renaming requirements so that e.g.
-                                // `use super;` doesn't work, but `use super as name;` does.
-                                // Fall through here to get an error from `early_resolve_...`.
-                            }
-                        }
-
-                        let binding = self.early_resolve_ident_in_lexical_scope(
-                            ident, ns, None, true, parent_scope, record_used, record_used, path_span
-                        );
-                        return binding.map_err(|determinacy| (determinacy, Weak::No));
+                let parent_scope = self.dummy_parent_scope();
+                let binding = self.early_resolve_ident_in_lexical_scope(
+                    ident, ScopeSet::AbsolutePath(ns), &parent_scope,
+                    record_used, record_used, path_span,
+                );
+                return binding.map_err(|determinacy| (determinacy, Weak::No));
+            }
+            ModuleOrUniformRoot::ExternPrelude => {
+                assert!(!restricted_shadowing);
+                return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
+                    Ok(binding)
+                } else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
+                    // Macro-expanded `extern crate` items can add names to extern prelude.
+                    Err((Undetermined, Weak::No))
+                } else {
+                    Err((Determined, Weak::No))
+                }
+            }
+            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 == keywords::Crate.name() ||
+                        ident.name == keywords::DollarCrate.name() {
+                        let module = self.resolve_crate_root(ident);
+                        let binding = (module, ty::Visibility::Public,
+                                        module.span, Mark::root())
+                                        .to_name_binding(self.arenas);
+                        return Ok(binding);
+                    } else if ident.name == keywords::Super.name() ||
+                                ident.name == keywords::SelfValue.name() {
+                        // FIXME: Implement these with renaming requirements so that e.g.
+                        // `use super;` doesn't work, but `use super as name;` does.
+                        // Fall through here to get an error from `early_resolve_...`.
                     }
                 }
+
+                let binding = self.early_resolve_ident_in_lexical_scope(
+                    ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span
+                );
+                return binding.map_err(|determinacy| (determinacy, Weak::No));
             }
         };
 
@@ -334,7 +339,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
             }
             let module = match glob_import.imported_module.get() {
                 Some(ModuleOrUniformRoot::Module(module)) => module,
-                Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
+                Some(_) => continue,
                 None => return Err((Undetermined, Weak::Yes)),
             };
             let (orig_current_module, mut ident) = (self.current_module, ident.modern());
@@ -967,9 +972,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
 
             return if all_ns_failed {
                 let resolutions = match module {
-                    ModuleOrUniformRoot::Module(module) =>
-                        Some(module.resolutions.borrow()),
-                    ModuleOrUniformRoot::UniformRoot(_) => None,
+                    ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()),
+                    _ => None,
                 };
                 let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
                 let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
@@ -1007,7 +1011,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                             format!("no `{}` in the root{}", ident, lev_suggestion)
                         }
                     }
-                    ModuleOrUniformRoot::UniformRoot(_) => {
+                    _ => {
                         if !ident.is_path_segment_keyword() {
                             format!("no `{}` external crate{}", ident, lev_suggestion)
                         } else {
@@ -1108,9 +1112,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
         let module = match directive.imported_module.get().unwrap() {
             ModuleOrUniformRoot::Module(module) => module,
-            ModuleOrUniformRoot::UniformRoot(_) => {
-                self.session.span_err(directive.span,
-                    "cannot glob-import all possible crates");
+            _ => {
+                self.session.span_err(directive.span, "cannot glob-import all possible crates");
                 return;
             }
         };
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index a1e51402830c9..cd674c05abdd2 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -814,11 +814,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
             report_unexpected_def(def);
             return self.tcx.types.err;
         }
-        // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
-
-        self.demand_eqtype(pat.span, expected, pat_ty);
 
         let variant = match def {
             Def::Err => {
@@ -836,6 +831,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
         };
+
+        // Replace constructor type with constructed type for tuple struct patterns.
+        let pat_ty = pat_ty.fn_sig(tcx).output();
+        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
+
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
         // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index be448f960df3f..184f4bdc25606 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -43,7 +43,7 @@ use ast::{BinOpKind, UnOp};
 use ast::{RangeEnd, RangeSyntax};
 use {ast, attr};
 use source_map::{self, SourceMap, Spanned, respan};
-use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, edition::Edition};
+use syntax_pos::{self, Span, MultiSpan, BytePos, FileName};
 use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId};
 use parse::{self, SeqSep, classify, token};
 use parse::lexer::TokenAndSpan;
@@ -1403,11 +1403,7 @@ impl<'a> Parser<'a> {
                 // definition...
 
                 // We don't allow argument names to be left off in edition 2018.
-                if p.span.edition() >= Edition::Edition2018 {
-                    p.parse_arg_general(true)
-                } else {
-                    p.parse_arg_general(false)
-                }
+                p.parse_arg_general(p.span.rust_2018())
             })?;
             generics.where_clause = self.parse_where_clause()?;
 
@@ -1600,9 +1596,9 @@ impl<'a> Parser<'a> {
             impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
             TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
         } else if self.check_keyword(keywords::Dyn) &&
-                  (self.span.edition() == Edition::Edition2018 ||
+                  (self.span.rust_2018() ||
                    self.look_ahead(1, |t| t.can_begin_bound() &&
-                                         !can_continue_type_after_non_fn_ident(t))) {
+                                          !can_continue_type_after_non_fn_ident(t))) {
             self.bump(); // `dyn`
             // Always parse bounds greedily for better error recovery.
             let bounds = self.parse_generic_bounds()?;
@@ -2043,8 +2039,9 @@ impl<'a> Parser<'a> {
 
         let lo = self.meta_var_span.unwrap_or(self.span);
         let mut segments = Vec::new();
+        let mod_sep_ctxt = self.span.ctxt();
         if self.eat(&token::ModSep) {
-            segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
+            segments.push(PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
         self.parse_path_segments(&mut segments, style, enable_warning)?;
 
@@ -2382,8 +2379,7 @@ impl<'a> Parser<'a> {
                     hi = path.span;
                     return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
                 }
-                if self.span.edition() >= Edition::Edition2018 &&
-                    self.check_keyword(keywords::Async)
+                if self.span.rust_2018() && self.check_keyword(keywords::Async)
                 {
                     if self.is_async_block() { // check for `async {` and `async move {`
                         return self.parse_async_block(attrs);
@@ -3395,7 +3391,7 @@ impl<'a> Parser<'a> {
         } else {
             Movability::Movable
         };
-        let asyncness = if self.span.edition() >= Edition::Edition2018 {
+        let asyncness = if self.span.rust_2018() {
             self.parse_asyncness()
         } else {
             IsAsync::NotAsync
@@ -4508,9 +4504,7 @@ impl<'a> Parser<'a> {
     fn is_try_block(&mut self) -> bool {
         self.token.is_keyword(keywords::Try) &&
         self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
-
-        self.span.edition() >= Edition::Edition2018 &&
-
+        self.span.rust_2018() &&
         // prevent `while try {} {}`, `if try {} {} else {}`, etc.
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
@@ -7599,8 +7593,11 @@ impl<'a> Parser<'a> {
                       self.check(&token::BinOp(token::Star)) ||
                       self.is_import_coupler() {
             // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
+            let mod_sep_ctxt = self.span.ctxt();
             if self.eat(&token::ModSep) {
-                prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
+                prefix.segments.push(
+                    PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))
+                );
             }
 
             if self.eat(&token::BinOp(token::Star)) {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 45eaf1d3190f2..62c8f2a78e129 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -325,6 +325,16 @@ impl Span {
                                                     |einfo| einfo.edition)
     }
 
+    #[inline]
+    pub fn rust_2015(&self) -> bool {
+        self.edition() == edition::Edition::Edition2015
+    }
+
+    #[inline]
+    pub fn rust_2018(&self) -> bool {
+        self.edition() >= edition::Edition::Edition2018
+    }
+
     /// Return the source callee.
     ///
     /// Returns `None` if the supplied span has no expansion trace,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 361353c82e25c..e333a4f2176f5 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -12,7 +12,6 @@
 //! allows bidirectional lookup; i.e. given a value, one can easily find the
 //! type, and vice versa.
 
-use edition::Edition;
 use hygiene::SyntaxContext;
 use {Span, DUMMY_SP, GLOBALS};
 
@@ -444,7 +443,7 @@ impl Ident {
     pub fn is_unused_keyword(self) -> bool {
         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
         self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() ||
-        self.name.is_unused_keyword_2018() && self.span.edition() == Edition::Edition2018
+        self.name.is_unused_keyword_2018() && self.span.rust_2018()
     }
 
     /// Returns `true` if the token is either a special identifier or a keyword.
diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr
index ee98873064fc4..d288d7295120c 100644
--- a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr
+++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr
@@ -14,7 +14,7 @@ note: `helper` could also refer to the attribute macro imported here
    |
 LL | use plugin::helper;
    |     ^^^^^^^^^^^^^^
-   = help: use `self::helper` to refer to this attribute macro unambiguously
+   = help: use `crate::helper` to refer to this attribute macro unambiguously
 
 error: aborting due to previous error
 
diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr
index 34b21ea26830c..79dc922b9db2c 100644
--- a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr
+++ b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr
@@ -16,7 +16,7 @@ note: `repr` could also refer to the attribute macro imported here
    |
 LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
-   = help: use `self::repr` to refer to this attribute macro unambiguously
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
 
 error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
   --> $DIR/ambiguous-builtin-attrs.rs:11:19
@@ -30,7 +30,7 @@ note: `repr` could also refer to the attribute macro imported here
    |
 LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
-   = help: use `self::repr` to refer to this attribute macro unambiguously
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
 
 error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
   --> $DIR/ambiguous-builtin-attrs.rs:20:34
@@ -44,7 +44,7 @@ note: `repr` could also refer to the attribute macro imported here
    |
 LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
-   = help: use `self::repr` to refer to this attribute macro unambiguously
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
 
 error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
   --> $DIR/ambiguous-builtin-attrs.rs:22:11
@@ -58,7 +58,7 @@ note: `repr` could also refer to the attribute macro imported here
    |
 LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
-   = help: use `self::repr` to refer to this attribute macro unambiguously
+   = help: use `crate::repr` to refer to this attribute macro unambiguously
 
 error[E0659]: `feature` is ambiguous (built-in attribute vs any other name)
   --> $DIR/ambiguous-builtin-attrs.rs:3:4
@@ -72,7 +72,7 @@ note: `feature` could also refer to the attribute macro imported here
    |
 LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
-   = help: use `self::feature` to refer to this attribute macro unambiguously
+   = help: use `crate::feature` to refer to this attribute macro unambiguously
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs
new file mode 100644
index 0000000000000..5bb818f7d23ba
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs
@@ -0,0 +1,19 @@
+// edition:2015
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive2015)]
+pub fn derive_2015(_: TokenStream) -> TokenStream {
+    "
+    use import::Path;
+
+    fn check_absolute() {
+        let x = ::absolute::Path;
+    }
+    ".parse().unwrap()
+}
diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
index f04782fac4d2d..cc50fefc46453 100644
--- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
+++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
@@ -14,7 +14,7 @@ note: `my_attr` could also refer to the attribute macro imported here
    |
 LL | use derive_helper_shadowing::*;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: use `self::my_attr` to refer to this attribute macro unambiguously
+   = help: use `crate::my_attr` to refer to this attribute macro unambiguously
 
 error: aborting due to previous error
 
diff --git a/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs
new file mode 100644
index 0000000000000..f8d6bc5e0785d
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs
@@ -0,0 +1,24 @@
+// compile-pass
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod import {
+    pub struct Path;
+}
+mod absolute {
+    pub struct Path;
+}
+
+mod check {
+    #[derive(Derive2015)] // OK
+    struct S;
+
+    fn check() {
+        Path;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/auxiliary/absolute.rs b/src/test/ui/editions/auxiliary/absolute.rs
new file mode 100644
index 0000000000000..d596f97355f4c
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/absolute.rs
@@ -0,0 +1 @@
+pub struct Path;
diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs
new file mode 100644
index 0000000000000..c72331ca2e119
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs
@@ -0,0 +1,31 @@
+// edition:2015
+
+#[macro_export]
+macro_rules! gen_imports { () => {
+    use import::Path;
+    use std::collections::LinkedList;
+
+    fn check_absolute() {
+        ::absolute::Path;
+        ::std::collections::LinkedList::<u8>::new();
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_glob { () => {
+    use *;
+}}
+
+#[macro_export]
+macro_rules! gen_gated { () => {
+    fn check_gated() {
+        enum E { A }
+        use E::*;
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_ambiguous { () => {
+    use Ambiguous;
+    type A = ::edition_imports_2015::Path;
+}}
diff --git a/src/test/ui/editions/auxiliary/edition-imports-2018.rs b/src/test/ui/editions/auxiliary/edition-imports-2018.rs
new file mode 100644
index 0000000000000..b08dc499a0ddd
--- /dev/null
+++ b/src/test/ui/editions/auxiliary/edition-imports-2018.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#[macro_export]
+macro_rules! gen_imports { () => {
+    use import::Path;
+    use std::collections::LinkedList;
+
+    fn check_absolute() {
+        ::absolute::Path;
+        ::std::collections::LinkedList::<u8>::new();
+    }
+}}
+
+#[macro_export]
+macro_rules! gen_glob { () => {
+    use *;
+}}
diff --git a/src/test/ui/editions/edition-imports-2015.rs b/src/test/ui/editions/edition-imports-2015.rs
new file mode 100644
index 0000000000000..b89ca28e279db
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2015.rs
@@ -0,0 +1,28 @@
+// edition:2015
+// compile-flags:--extern absolute
+// aux-build:edition-imports-2018.rs
+// aux-build:absolute.rs
+
+#![feature(uniform_paths)]
+
+#[macro_use]
+extern crate edition_imports_2018;
+
+mod check {
+    mod import {
+        pub struct Path;
+    }
+
+    gen_imports!(); // OK
+
+    fn check() {
+        Path;
+        LinkedList::<u8>::new();
+    }
+}
+
+mod check_glob {
+    gen_glob!(); //~ ERROR cannot glob-import all possible crates
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-2015.stderr b/src/test/ui/editions/edition-imports-2015.stderr
new file mode 100644
index 0000000000000..fb6b2e64ef5b8
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2015.stderr
@@ -0,0 +1,10 @@
+error: cannot glob-import all possible crates
+  --> $DIR/edition-imports-2015.rs:25:5
+   |
+LL |     gen_glob!(); //~ ERROR cannot glob-import all possible crates
+   |     ^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs
new file mode 100644
index 0000000000000..dcdbf0d050be1
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2018.rs
@@ -0,0 +1,27 @@
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod import {
+    pub struct Path;
+}
+mod absolute {
+    pub struct Path;
+}
+
+mod check {
+    gen_imports!(); // OK
+
+    fn check() {
+        Path;
+        LinkedList::<u8>::new();
+    }
+}
+
+mod check_glob {
+    gen_glob!(); //~ ERROR cannot glob-import all possible crates
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr
new file mode 100644
index 0000000000000..944f42ee0451b
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-2018.stderr
@@ -0,0 +1,10 @@
+error: cannot glob-import all possible crates
+  --> $DIR/edition-imports-2018.rs:24:5
+   |
+LL |     gen_glob!(); //~ ERROR cannot glob-import all possible crates
+   |     ^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
new file mode 100644
index 0000000000000..53ec3867f0110
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// compile-flags:--extern edition_imports_2015
+// aux-build:edition-imports-2015.rs
+
+mod edition_imports_2015 {
+    pub struct Path;
+}
+
+pub struct Ambiguous {}
+
+mod check {
+    pub struct Ambiguous {}
+
+    fn check() {
+        edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
+                                                //~| ERROR `edition_imports_2015` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr
new file mode 100644
index 0000000000000..ac2bf21c5c0ba
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr
@@ -0,0 +1,40 @@
+error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution)
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9
+   |
+LL |         edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
+   |
+note: `Ambiguous` could refer to the struct defined here
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:9:1
+   |
+LL | pub struct Ambiguous {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `crate::Ambiguous` to refer to this struct unambiguously
+note: `Ambiguous` could also refer to the struct defined here
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:12:5
+   |
+LL |     pub struct Ambiguous {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: use `self::Ambiguous` to refer to this struct unambiguously
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution)
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9
+   |
+LL |         edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
+   |
+   = note: `edition_imports_2015` could refer to an extern crate passed with `--extern`
+note: `edition_imports_2015` could also refer to the module defined here
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:5:1
+   |
+LL | / mod edition_imports_2015 {
+LL | |     pub struct Path;
+LL | | }
+   | |_^
+   = help: use `crate::edition_imports_2015` to refer to this module unambiguously
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.rs b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs
new file mode 100644
index 0000000000000..a1bf4f5eb51dc
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// aux-build:edition-imports-2015.rs
+// error-pattern: imports can only refer to extern crate names passed with `--extern`
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod check {
+    gen_gated!();
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr
new file mode 100644
index 0000000000000..7c1837e3f56e3
--- /dev/null
+++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr
@@ -0,0 +1,22 @@
+error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
+  --> <::edition_imports_2015::gen_gated macros>:1:50
+   |
+LL | (  ) => { fn check_gated (  ) { enum E { A } use E :: * ; } }
+   |                                                  ^
+   | 
+  ::: $DIR/edition-imports-virtual-2015-gated.rs:9:5
+   |
+LL |     gen_gated!();
+   |     ------------- not an extern crate passed with `--extern`
+   |
+   = help: add #![feature(uniform_paths)] to the crate attributes to enable
+note: this import refers to the enum defined here
+  --> $DIR/edition-imports-virtual-2015-gated.rs:9:5
+   |
+LL |     gen_gated!();
+   |     ^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
index fb05b95a96dc6..37633c7a4415f 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
@@ -43,6 +43,7 @@ mod inner2 {
 
 fn main() {
     panic!(); //~ ERROR `panic` is ambiguous
+              //~| ERROR `panic` is ambiguous
 }
 
 mod inner3 {
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index 962294e48caef..1978648e206f1 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -22,7 +22,7 @@ LL | use inner1::*;
    = help: consider adding an explicit import of `exported` to disambiguate
 
 error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/local-modularized-tricky-fail-1.rs:56:1
+  --> $DIR/local-modularized-tricky-fail-1.rs:57:1
    |
 LL | include!(); //~ ERROR `include` is ambiguous
    | ^^^^^^^ ambiguous name
@@ -38,7 +38,7 @@ LL | |     }
 ...
 LL |       define_include!();
    |       ------------------ in this macro invocation
-   = help: use `self::include` to refer to this macro unambiguously
+   = help: use `crate::include` to refer to this macro unambiguously
 
 error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
   --> $DIR/local-modularized-tricky-fail-1.rs:45:5
@@ -57,13 +57,13 @@ LL | |     }
 ...
 LL |       define_panic!();
    |       ---------------- in this macro invocation
-   = help: use `self::panic` to refer to this macro unambiguously
+   = help: use `crate::panic` to refer to this macro unambiguously
 
 error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> <::std::macros::panic macros>:1:13
+  --> $DIR/local-modularized-tricky-fail-1.rs:45:5
    |
-LL | (  ) => ( { panic ! ( "explicit panic" ) } ) ; ( $ msg : expr ) => (
-   |             ^^^^^ ambiguous name
+LL |     panic!(); //~ ERROR `panic` is ambiguous
+   |     ^^^^^^^^^ ambiguous name
    |
    = note: `panic` could refer to a macro from prelude
 note: `panic` could also refer to the macro defined here
@@ -76,7 +76,8 @@ LL | |     }
 ...
 LL |       define_panic!();
    |       ---------------- in this macro invocation
-   = help: use `self::panic` to refer to this macro unambiguously
+   = help: use `crate::panic` to refer to this macro unambiguously
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr
index 8e8742f849bf0..3f481b0cfb0df 100644
--- a/src/test/ui/imports/macro-paths.stderr
+++ b/src/test/ui/imports/macro-paths.stderr
@@ -34,7 +34,7 @@ LL | / pub mod baz {
 LL | |     pub use two_macros::m;
 LL | | }
    | |_^
-   = help: use `self::baz` to refer to this module unambiguously
+   = help: use `crate::baz` to refer to this module unambiguously
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr
index 2135d63c80ec2..9d61799713b04 100644
--- a/src/test/ui/macros/restricted-shadowing-legacy.stderr
+++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr
@@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             m!(); //~ ERROR `m` is ambiguous
    |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
    |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         m!(); //~ ERROR `m` is ambiguous
    |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         m!(); //~ ERROR `m` is ambiguous
    |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             m!(); //~ ERROR `m` is ambiguous
    |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
    |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -141,6 +159,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         m!(); //~ ERROR `m` is ambiguous
    |         ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
@@ -164,6 +185,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |         macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous
    |                                          ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-legacy.rs:88:9
diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr
index 2449e8512d3cd..398a7660d3093 100644
--- a/src/test/ui/macros/restricted-shadowing-modern.stderr
+++ b/src/test/ui/macros/restricted-shadowing-modern.stderr
@@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |                 m!(); //~ ERROR `m` is ambiguous
    |                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
@@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
    |                                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
@@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             m!(); //~ ERROR `m` is ambiguous
    |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
@@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             m!(); //~ ERROR `m` is ambiguous
    |             ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
@@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |                 m!(); //~ ERROR `m` is ambiguous
    |                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
@@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name
    |
 LL |             macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
    |                                 ^ ambiguous name
+...
+LL | include!();
+   | ----------- in this macro invocation
    |
 note: `m` could refer to the macro defined here
   --> $DIR/restricted-shadowing-modern.rs:91:9
diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs
new file mode 100644
index 0000000000000..d9c50e75c4944
--- /dev/null
+++ b/src/test/ui/match/match-fn-call.rs
@@ -0,0 +1,12 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("foo");
+    match path {
+        Path::new("foo") => println!("foo"),
+        //~^ ERROR expected tuple struct/variant
+        Path::new("bar") => println!("bar"),
+        //~^ ERROR expected tuple struct/variant
+        _ => (),
+    }
+}
diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr
new file mode 100644
index 0000000000000..4e24621706bdb
--- /dev/null
+++ b/src/test/ui/match/match-fn-call.stderr
@@ -0,0 +1,15 @@
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:6:9
+   |
+LL |         Path::new("foo") => println!("foo"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:8:9
+   |
+LL |         Path::new("bar") => println!("bar"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs
deleted file mode 100644
index 4819711115c27..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-// This test is similar to `ambiguity-macros.rs`, but nested in a module.
-
-mod foo {
-    pub use std::io;
-    //~^ ERROR `std` is ambiguous
-
-    macro_rules! m {
-        () => {
-            mod std {
-                pub struct io;
-            }
-        }
-    }
-    m!();
-}
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr
deleted file mode 100644
index 204e0a7e1411e..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/ambiguity-macros-nested.rs:16:13
-   |
-LL |     pub use std::io;
-   |             ^^^ ambiguous name
-   |
-   = note: `std` could refer to a built-in extern crate
-   = help: use `::std` to refer to this extern crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity-macros-nested.rs:21:13
-   |
-LL | /             mod std {
-LL | |                 pub struct io;
-LL | |             }
-   | |_____________^
-...
-LL |       m!();
-   |       ----- in this macro invocation
-   = help: use `self::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs
deleted file mode 100644
index 148320de556d3..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-// This test is similar to `ambiguity.rs`, but with macros defining local items.
-
-use std::io;
-//~^ ERROR `std` is ambiguous
-
-macro_rules! m {
-    () => {
-        mod std {
-            pub struct io;
-        }
-    }
-}
-m!();
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr
deleted file mode 100644
index ac8d3b9d0cbe4..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/ambiguity-macros.rs:15:5
-   |
-LL | use std::io;
-   |     ^^^ ambiguous name
-   |
-   = note: `std` could refer to a built-in extern crate
-   = help: use `::std` to refer to this extern crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity-macros.rs:20:9
-   |
-LL | /         mod std {
-LL | |             pub struct io;
-LL | |         }
-   | |_________^
-...
-LL |   m!();
-   |   ----- in this macro invocation
-   = help: use `self::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs
deleted file mode 100644
index 2791d4580daf1..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-// This test is similar to `ambiguity.rs`, but nested in a module.
-
-mod foo {
-    pub use std::io;
-    //~^ ERROR `std` is ambiguous
-
-    mod std {
-        pub struct io;
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr
deleted file mode 100644
index 7bcfc563d39fc..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/ambiguity-nested.rs:16:13
-   |
-LL |     pub use std::io;
-   |             ^^^ ambiguous name
-   |
-   = note: `std` could refer to a built-in extern crate
-   = help: use `::std` to refer to this extern crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity-nested.rs:19:5
-   |
-LL | /     mod std {
-LL | |         pub struct io;
-LL | |     }
-   | |_____^
-   = help: use `self::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs
deleted file mode 100644
index 2bfbb6b287153..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-use std::io;
-//~^ ERROR `std` is ambiguous
-
-mod std {
-    pub struct io;
-}
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr
deleted file mode 100644
index beeb74654e5b5..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/ambiguity.rs:13:5
-   |
-LL | use std::io;
-   |     ^^^ ambiguous name
-   |
-   = note: `std` could refer to a built-in extern crate
-   = help: use `::std` to refer to this extern crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity.rs:16:1
-   |
-LL | / mod std {
-LL | |     pub struct io;
-LL | | }
-   | |_^
-   = help: use `self::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs
deleted file mode 100644
index 2853b4b3a5b3f..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-struct std;
-
-fn main() {
-    fn std() {}
-    enum std {}
-    use std as foo;
-    //~^ ERROR `std` is ambiguous
-    //~| ERROR `std` is ambiguous
-}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr
deleted file mode 100644
index 5d539e2d59f15..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/block-scoped-shadow.rs:18:9
-   |
-LL |     use std as foo;
-   |         ^^^ ambiguous name
-   |
-note: `std` could refer to the enum defined here
-  --> $DIR/block-scoped-shadow.rs:17:5
-   |
-LL |     enum std {}
-   |     ^^^^^^^^^^^
-note: `std` could also refer to the struct defined here
-  --> $DIR/block-scoped-shadow.rs:13:1
-   |
-LL | struct std;
-   | ^^^^^^^^^^^
-   = help: use `self::std` to refer to this struct unambiguously
-
-error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/block-scoped-shadow.rs:18:9
-   |
-LL |     use std as foo;
-   |         ^^^ ambiguous name
-   |
-note: `std` could refer to the function defined here
-  --> $DIR/block-scoped-shadow.rs:16:5
-   |
-LL |     fn std() {}
-   |     ^^^^^^^^^^^
-note: `std` could also refer to the unit struct defined here
-  --> $DIR/block-scoped-shadow.rs:13:1
-   |
-LL | struct std;
-   | ^^^^^^^^^^^
-   = help: use `self::std` to refer to this unit struct unambiguously
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs
deleted file mode 100644
index ef2a1e3c70c6f..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-// Dummy import that previously introduced uniform path canaries.
-use std;
-
-// fn version() -> &'static str {""}
-
-mod foo {
-    // Error wasn't reported, despite `version` being commented out above.
-    use crate::version; //~ ERROR unresolved import `crate::version`
-
-    fn bar() {
-        version();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr
deleted file mode 100644
index 6dcc451c60a61..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `crate::version`
-  --> $DIR/issue-54253.rs:20:9
-   |
-LL |     use crate::version; //~ ERROR unresolved import `crate::version`
-   |         ^^^^^^^^^^^^^^ no `version` in the root
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs
deleted file mode 100644
index 05048cfd45105..0000000000000
--- a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// run-pass
-// edition:2018
-
-use std;
-use std::io;
-
-mod foo {
-    pub use std as my_std;
-}
-
-mod bar {
-    pub use std::{self};
-}
-
-fn main() {
-    io::stdout();
-    self::std::io::stdout();
-    foo::my_std::io::stdout();
-    bar::std::io::stdout();
-}
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
index ac8d3b9d0cbe4..a9e6da8f211b3 100644
--- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
@@ -16,7 +16,7 @@ LL | |         }
 ...
 LL |   m!();
    |   ----- in this macro invocation
-   = help: use `self::std` to refer to this module unambiguously
+   = help: use `crate::std` to refer to this module unambiguously
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
index beeb74654e5b5..b1feb82fba90d 100644
--- a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
@@ -13,7 +13,7 @@ LL | / mod std {
 LL | |     pub struct io;
 LL | | }
    | |_^
-   = help: use `self::std` to refer to this module unambiguously
+   = help: use `crate::std` to refer to this module unambiguously
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
index aa46947f93f4b..0088296b1a471 100644
--- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
@@ -16,7 +16,7 @@ LL | / mod sub {
 LL | |     pub fn bar() {}
 LL | | }
    | |_^
-   = help: use `self::sub` to refer to this module unambiguously
+   = help: use `crate::sub` to refer to this module unambiguously
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
index 010b9efad393b..213f723385b1c 100644
--- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
@@ -14,7 +14,7 @@ note: `Foo` could also refer to the enum defined here
    |
 LL | enum Foo {}
    | ^^^^^^^^^^^
-   = help: use `self::Foo` to refer to this enum unambiguously
+   = help: use `crate::Foo` to refer to this enum unambiguously
 
 error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
   --> $DIR/block-scoped-shadow.rs:26:9
@@ -32,7 +32,7 @@ note: `std` could also refer to the struct defined here
    |
 LL | struct std;
    | ^^^^^^^^^^^
-   = help: use `self::std` to refer to this struct unambiguously
+   = help: use `crate::std` to refer to this struct unambiguously
 
 error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
   --> $DIR/block-scoped-shadow.rs:26:9
@@ -50,7 +50,7 @@ note: `std` could also refer to the unit struct defined here
    |
 LL | struct std;
    | ^^^^^^^^^^^
-   = help: use `self::std` to refer to this unit struct unambiguously
+   = help: use `crate::std` to refer to this unit struct unambiguously
 
 error: aborting due to 3 previous errors