about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-08-09 16:29:22 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-08-14 07:06:50 +0300
commitf9b1176eefb84686c76dde1b53a47ee0eb765d89 (patch)
tree6ca9d6d36cca31c593307028bfcbdf9834402b87
parentcd47831bf04175aad44d94c580a3d08f432dc23a (diff)
downloadrust-f9b1176eefb84686c76dde1b53a47ee0eb765d89.tar.gz
rust-f9b1176eefb84686c76dde1b53a47ee0eb765d89.zip
rustc_resolve: fix special-case for one-segment import paths.
-rw-r--r--src/librustc_metadata/creader.rs28
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs27
-rw-r--r--src/librustc_resolve/lib.rs220
-rw-r--r--src/librustc_resolve/macros.rs24
-rw-r--r--src/librustc_resolve/resolve_imports.rs236
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/test/compile-fail/dollar-crate-is-keyword.rs6
-rw-r--r--src/test/compile-fail/import-crate-var.rs7
-rw-r--r--src/test/compile-fail/keyword-extern-as-identifier.rs2
-rw-r--r--src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs6
-rw-r--r--src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs3
-rw-r--r--src/test/run-pass/issue-52140/auxiliary/some_crate.rs15
-rw-r--r--src/test/run-pass/issue-52140/main.rs21
-rw-r--r--src/test/run-pass/issue-52141/auxiliary/some_crate.rs15
-rw-r--r--src/test/run-pass/issue-52141/main.rs24
-rw-r--r--src/test/run-pass/issue-52705/auxiliary/png.rs13
-rw-r--r--src/test/run-pass/issue-52705/main.rs22
17 files changed, 433 insertions, 238 deletions
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index d3b70933e2c..a10bb3e25df 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -1139,32 +1139,4 @@ impl<'a> CrateLoader<'a> {
 
         cnum
     }
-
-    pub fn process_use_extern(
-        &mut self,
-        name: Symbol,
-        span: Span,
-        id: ast::NodeId,
-        definitions: &Definitions,
-    ) -> CrateNum {
-        let cnum = self.resolve_crate(
-            &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
-        ).0;
-
-        let def_id = definitions.opt_local_def_id(id).unwrap();
-        let path_len = definitions.def_path(def_id.index).data.len();
-
-        self.update_extern_crate(
-            cnum,
-            ExternCrate {
-                src: ExternCrateSource::Use,
-                span,
-                path_len,
-                direct: true,
-            },
-            &mut FxHashSet(),
-        );
-
-        cnum
-    }
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index bf87b00c149..06bc41548b9 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -17,7 +17,7 @@ use macros::{InvocationData, LegacyScope};
 use resolve_imports::ImportDirective;
 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
-use {PerNS, Resolver, ResolverArenas};
+use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas};
 use Namespace::{self, TypeNS, ValueNS, MacroNS};
 use {resolve_error, resolve_struct_error, ResolutionError};
 
@@ -175,7 +175,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                             ModuleKind::Def(_, name) => name,
                             ModuleKind::Block(..) => unreachable!(),
                         };
-                        source.name = crate_name;
+                        // HACK(eddyb) unclear how good this is, but keeping `$crate`
+                        // in `source` breaks `src/test/compile-fail/import-crate-var.rs`,
+                        // while the current crate doesn't have a valid `crate_name`.
+                        if crate_name != keywords::Invalid.name() {
+                            source.name = crate_name;
+                        }
                         if rename.is_none() {
                             ident.name = crate_name;
                         }
@@ -187,6 +192,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                 }
 
+                if ident.name == keywords::Crate.name() {
+                    self.session.span_err(ident.span,
+                        "crate root imports need to be explicitly named: \
+                         `use crate as name;`");
+                }
+
                 let subclass = SingleImport {
                     target: ident,
                     source,
@@ -299,7 +310,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     root_id: item.id,
                     id: item.id,
                     parent,
-                    imported_module: Cell::new(Some(module)),
+                    imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
                     subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
                     root_span: item.span,
                     span: item.span,
@@ -701,7 +712,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
             root_id: item.id,
             id: item.id,
             parent: graph_root,
-            imported_module: Cell::new(Some(module)),
+            imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
             subclass: ImportDirectiveSubclass::MacroUse,
             root_span: span,
             span,
@@ -721,7 +732,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         } else {
             for (name, span) in legacy_imports.imports {
                 let ident = Ident::with_empty_ctxt(name);
-                let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span);
+                let result = self.resolve_ident_in_module(
+                    ModuleOrUniformRoot::Module(module),
+                    ident,
+                    MacroNS,
+                    false,
+                    span,
+                );
                 if let Ok(binding) = result {
                     let directive = macro_use_directive(span);
                     self.potentially_unused_imports.push(directive);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e31e2cc1dff..992ea12ffa2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -953,9 +953,20 @@ impl<'a> LexicalScopeBinding<'a> {
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum ModuleOrUniformRoot<'a> {
+    /// Regular module.
+    Module(Module<'a>),
+
+    /// The `{{root}}` (`CrateRoot` aka "global") / `extern` initial segment
+    /// in which external crates resolve, and also `crate` (only in `{{root}}`,
+    /// but *not* `extern`), in the Rust 2018 edition.
+    UniformRoot(Name),
+}
+
 #[derive(Clone, Debug)]
 enum PathResult<'a> {
-    Module(Module<'a>),
+    Module(ModuleOrUniformRoot<'a>),
     NonModule(PathResolution),
     Indeterminate,
     Failed(Span, String, bool /* is the error from the last segment? */),
@@ -1583,11 +1594,13 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
         let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
         // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
-        match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) {
-            PathResult::Module(module) => *def = module.def().unwrap(),
+        match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
+            PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
+                *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
             PathResult::NonModule(..) => match self.resolve_path(
+                None,
                 &path,
                 None,
                 true,
@@ -1599,6 +1612,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 }
                 _ => {}
             },
+            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
             PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
                 error_callback(self, span, ResolutionError::FailedToResolve(&msg));
@@ -1881,7 +1895,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             };
 
             let item = self.resolve_ident_in_module_unadjusted(
-                module, ident, ns, false, record_used, path_span,
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                record_used,
+                path_span,
             );
             if let Ok(binding) = item {
                 // The ident resolves to an item.
@@ -1906,7 +1925,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             let orig_current_module = self.current_module;
             self.current_module = module; // Lexical resolutions can never be a privacy error.
             let result = self.resolve_ident_in_module_unadjusted(
-                module, ident, ns, false, record_used, path_span,
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                record_used,
+                path_span,
             );
             self.current_module = orig_current_module;
 
@@ -1954,8 +1978,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 return Some(LexicalScopeBinding::Item(binding));
             }
             if let Some(prelude) = self.prelude {
-                if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
-                                                                        false, false, path_span) {
+                if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
+                    ModuleOrUniformRoot::Module(prelude),
+                    ident,
+                    ns,
+                    false,
+                    false,
+                    path_span,
+                ) {
                     return Some(LexicalScopeBinding::Item(binding));
                 }
             }
@@ -2013,7 +2043,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
     }
 
     fn resolve_ident_in_module(&mut self,
-                               module: Module<'a>,
+                               module: ModuleOrUniformRoot<'a>,
                                mut ident: Ident,
                                ns: Namespace,
                                record_used: bool,
@@ -2021,8 +2051,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                                -> Result<&'a NameBinding<'a>, Determinacy> {
         ident.span = ident.span.modern();
         let orig_current_module = self.current_module;
-        if let Some(def) = ident.span.adjust(module.expansion) {
-            self.current_module = self.macro_def_scope(def);
+        if let ModuleOrUniformRoot::Module(module) = module {
+            if let Some(def) = ident.span.adjust(module.expansion) {
+                self.current_module = self.macro_def_scope(def);
+            }
         }
         let result = self.resolve_ident_in_module_unadjusted(
             module, ident, ns, false, record_used, span,
@@ -2410,13 +2442,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             if def != Def::Err {
                 new_id = Some(def.def_id());
                 let span = trait_ref.path.span;
-                if let PathResult::Module(module) = self.resolve_path(
-                    &path,
-                    None,
-                    false,
-                    span,
-                    CrateLint::SimplePath(trait_ref.ref_id),
-                ) {
+                if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
+                    self.resolve_path(
+                        None,
+                        &path,
+                        None,
+                        false,
+                        span,
+                        CrateLint::SimplePath(trait_ref.ref_id),
+                    )
+                {
                     new_val = Some((module, trait_ref.clone()));
                 }
             }
@@ -2533,7 +2568,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         // If there is a TraitRef in scope for an impl, then the method must be in the
         // trait.
         if let Some((module, _)) = self.current_trait_ref {
-            if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() {
+            if self.resolve_ident_in_module(
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                span,
+            ).is_err() {
                 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
                 resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
             }
@@ -2908,9 +2949,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     (String::new(), "the crate root".to_string())
                 } else {
                     let mod_path = &path[..path.len() - 1];
-                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
+                    let mod_prefix = match this.resolve_path(None, mod_path, Some(TypeNS),
                                                              false, span, CrateLint::No) {
-                        PathResult::Module(module) => module.def(),
+                        PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
+                            module.def(),
                         _ => None,
                     }.map_or(String::new(), |def| format!("{} ", def.kind_name()));
                     (mod_prefix, format!("`{}`", names_to_string(mod_path)))
@@ -3319,6 +3361,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         }
 
         let result = match self.resolve_path(
+            None,
             &path,
             Some(ns),
             true,
@@ -3326,7 +3369,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             crate_lint,
         ) {
             PathResult::NonModule(path_res) => path_res,
-            PathResult::Module(module) if !module.is_normal() => {
+            PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
             }
             // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
@@ -3341,18 +3384,21 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             //
             // Such behavior is required for backward compatibility.
             // The same fallback is used when `a` resolves to nothing.
-            PathResult::Module(..) | PathResult::Failed(..)
+            PathResult::Module(ModuleOrUniformRoot::Module(_)) |
+            PathResult::Failed(..)
                     if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types
                            .contains_key(&path[0].name) => {
                 let prim = self.primitive_type_table.primitive_types[&path[0].name];
                 PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
             }
-            PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
+            PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
+                PathResolution::new(module.def().unwrap()),
             PathResult::Failed(span, msg, false) => {
                 resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 err_path_resolution()
             }
+            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
             PathResult::Failed(..) => return None,
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
@@ -3362,6 +3408,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
            path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
                 match self.resolve_path(
+                    None,
                     &[*path.last().unwrap()],
                     Some(ns),
                     false,
@@ -3369,7 +3416,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     CrateLint::No,
                 ) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
-                    PathResult::Module(module) => module.def().unwrap(),
+                    PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
+                        module.def().unwrap(),
                     _ => return Some(result),
                 }
             };
@@ -3384,13 +3432,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
     fn resolve_path(
         &mut self,
+        base_module: Option<ModuleOrUniformRoot<'a>>,
         path: &[Ident],
         opt_ns: Option<Namespace>, // `None` indicates a module path
         record_used: bool,
         path_span: Span,
         crate_lint: CrateLint,
     ) -> PathResult<'a> {
-        let mut module = None;
+        let mut module = base_module;
         let mut allow_super = true;
         let mut second_binding = None;
 
@@ -3412,49 +3461,48 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
             if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
                 let mut ctxt = ident.span.ctxt().modern();
-                module = Some(self.resolve_self(&mut ctxt, self.current_module));
+                module = Some(ModuleOrUniformRoot::Module(
+                    self.resolve_self(&mut ctxt, self.current_module)));
                 continue
             } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
                 let mut ctxt = ident.span.ctxt().modern();
-                let self_module = match i {
-                    0 => self.resolve_self(&mut ctxt, self.current_module),
-                    _ => module.unwrap(),
+                let self_module_parent = match i {
+                    0 => self.resolve_self(&mut ctxt, self.current_module).parent,
+                    _ => match module {
+                        Some(ModuleOrUniformRoot::Module(module)) => module.parent,
+                        _ => None,
+                    },
                 };
-                if let Some(parent) = self_module.parent {
-                    module = Some(self.resolve_self(&mut ctxt, parent));
+                if let Some(parent) = self_module_parent {
+                    module = Some(ModuleOrUniformRoot::Module(
+                        self.resolve_self(&mut ctxt, parent)));
                     continue
                 } else {
                     let msg = "There are too many initial `super`s.".to_string();
                     return PathResult::Failed(ident.span, msg, false);
                 }
-            } else if i == 0 && ns == TypeNS && name == keywords::Extern.name() {
-                continue;
             }
             allow_super = false;
 
             if ns == TypeNS {
+                if i == 0 {
+                    if name == keywords::Extern.name() ||
+                       name == keywords::CrateRoot.name() &&
+                       self.session.features_untracked().extern_absolute_paths &&
+                       self.session.rust_2018() {
+                        module = Some(ModuleOrUniformRoot::UniformRoot(name));
+                        continue;
+                    }
+                }
                 if (i == 0 && name == keywords::CrateRoot.name()) ||
                    (i == 0 && name == keywords::Crate.name()) ||
                    (i == 0 && name == keywords::DollarCrate.name()) ||
                    (i == 1 && name == keywords::Crate.name() &&
                               path[0].name == keywords::CrateRoot.name()) {
                     // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
-                    module = Some(self.resolve_crate_root(ident));
+                    module = Some(ModuleOrUniformRoot::Module(
+                        self.resolve_crate_root(ident)));
                     continue
-                } else if i == 1 && !ident.is_path_segment_keyword() {
-                    let prev_name = path[0].name;
-                    if prev_name == keywords::Extern.name() ||
-                       prev_name == keywords::CrateRoot.name() &&
-                       self.session.features_untracked().extern_absolute_paths &&
-                       self.session.rust_2018() {
-                        // `::extern_crate::a::b`
-                        let crate_id = self.crate_loader.process_path_extern(name, ident.span);
-                        let crate_root =
-                            self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
-                        self.populate_module_if_necessary(crate_root);
-                        module = Some(crate_root);
-                        continue
-                    }
                 }
             }
 
@@ -3513,7 +3561,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     let def = binding.def();
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
                     if let Some(next_module) = binding.module() {
-                        module = Some(next_module);
+                        module = Some(ModuleOrUniformRoot::Module(next_module));
                     } else if def == Def::ToolMod && i + 1 != path.len() {
                         let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
                         return PathResult::NonModule(PathResolution::new(def));
@@ -3537,14 +3585,18 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 }
                 Err(Undetermined) => return PathResult::Indeterminate,
                 Err(Determined) => {
-                    if let Some(module) = module {
+                    if let Some(ModuleOrUniformRoot::Module(module)) = module {
                         if opt_ns.is_some() && !module.is_normal() {
                             return PathResult::NonModule(PathResolution::with_unresolved_segments(
                                 module.def().unwrap(), path.len() - i
                             ));
                         }
                     }
-                    let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
+                    let module_def = match module {
+                        Some(ModuleOrUniformRoot::Module(module)) => module.def(),
+                        _ => None,
+                    };
+                    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);
@@ -3568,7 +3620,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
 
-        PathResult::Module(module.unwrap_or(self.graph_root))
+        PathResult::Module(module.unwrap_or_else(|| {
+            span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
+        }))
+
     }
 
     fn lint_if_path_starts_with_module(
@@ -3578,6 +3633,17 @@ 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
+        }
+
+        // In the 2015 edition there's no use in emitting lints unless the
+        // crate's already enabled the feature that we're going to suggest
+        if !self.session.features_untracked().crate_in_paths {
+            return
+        }
+
         let (diag_id, diag_span) = match crate_lint {
             CrateLint::No => return,
             CrateLint::SimplePath(id) => (id, path_span),
@@ -3620,24 +3686,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             }
         }
 
-        self.lint_path_starts_with_module(diag_id, diag_span);
-    }
-
-    fn lint_path_starts_with_module(&self, id: NodeId, span: Span) {
-        // In the 2018 edition this lint is a hard error, so nothing to do
-        if self.session.rust_2018() {
-            return
-        }
-        // In the 2015 edition there's no use in emitting lints unless the
-        // crate's already enabled the feature that we're going to suggest
-        if !self.session.features_untracked().crate_in_paths {
-            return
-        }
         let diag = lint::builtin::BuiltinLintDiagnostics
-            ::AbsPathWithModule(span);
+            ::AbsPathWithModule(diag_span);
         self.session.buffer_lint_with_diagnostic(
             lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-            id, span,
+            diag_id, diag_span,
             "absolute paths must start with `self`, `super`, \
             `crate`, or an external crate name in the 2018 edition",
             diag);
@@ -3782,8 +3835,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         // Look for associated items in the current trait.
         if let Some((module, _)) = self.current_trait_ref {
-            if let Ok(binding) =
-                    self.resolve_ident_in_module(module, ident, ns, false, module.span) {
+            if let Ok(binding) = self.resolve_ident_in_module(
+                    ModuleOrUniformRoot::Module(module),
+                    ident,
+                    ns,
+                    false,
+                    module.span,
+                ) {
                 let def = binding.def();
                 if filter_fn(def) {
                     return Some(if self.has_self.contains(&def.def_id()) {
@@ -3855,9 +3913,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
-            if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
+            if let PathResult::Module(module) = self.resolve_path(None, mod_path, Some(TypeNS),
                                                                   false, span, CrateLint::No) {
-                add_module_candidates(module, &mut names);
+                if let ModuleOrUniformRoot::Module(module) = module {
+                    add_module_candidates(module, &mut names);
+                }
             }
         }
 
@@ -4096,7 +4156,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         let mut found_traits = Vec::new();
         // Look for the current trait.
         if let Some((module, _)) = self.current_trait_ref {
-            if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() {
+            if self.resolve_ident_in_module(
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                module.span,
+            ).is_ok() {
                 let def_id = module.def_id().unwrap();
                 found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
             }
@@ -4144,8 +4210,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
                 continue
             }
-            if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span)
-                   .is_ok() {
+            if self.resolve_ident_in_module_unadjusted(
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                false,
+                module.span,
+            ).is_ok() {
                 let import_id = match binding.kind {
                     NameBindingKind::Import { directive, .. } => {
                         self.maybe_unused_trait_imports.insert(directive.id);
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index fe9d3c7eb99..44d0c888c5d 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -10,6 +10,7 @@
 
 use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
 use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
+use ModuleOrUniformRoot;
 use Namespace::{self, TypeNS, MacroNS};
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
@@ -538,7 +539,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), false, span, CrateLint::No) {
+            let res = self.resolve_path(None, &path, Some(MacroNS), false, span, CrateLint::No);
+            let def = match res {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => {
@@ -655,7 +657,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                 WhereToResolve::Module(module) => {
                     let orig_current_module = mem::replace(&mut self.current_module, module);
                     let binding = self.resolve_ident_in_module_unadjusted(
-                            module, ident, ns, true, record_used, path_span,
+                        ModuleOrUniformRoot::Module(module),
+                        ident,
+                        ns,
+                        true,
+                        record_used,
+                        path_span,
                     );
                     self.current_module = orig_current_module;
                     binding.map(MacroBinding::Modern)
@@ -715,9 +722,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     let mut result = Err(Determinacy::Determined);
                     if use_prelude {
                         if let Some(prelude) = self.prelude {
-                            if let Ok(binding) =
-                                    self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
-                                                                          false, false, path_span) {
+                            if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
+                                ModuleOrUniformRoot::Module(prelude),
+                                ident,
+                                ns,
+                                false,
+                                false,
+                                path_span,
+                            ) {
                                 result = Ok(MacroBinding::Global(binding));
                             }
                         }
@@ -893,7 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(&path, Some(MacroNS), true, span, CrateLint::No) {
+            match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 715292bc116..58f7532adaf 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -10,7 +10,7 @@
 
 use self::ImportDirectiveSubclass::*;
 
-use {AmbiguityError, CrateLint, Module, PerNS};
+use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS};
 use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use Resolver;
@@ -85,7 +85,8 @@ pub struct ImportDirective<'a> {
 
     pub parent: Module<'a>,
     pub module_path: Vec<Ident>,
-    pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
+    /// The resolution of `module_path`.
+    pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
     pub subclass: ImportDirectiveSubclass<'a>,
     pub vis: Cell<ty::Visibility>,
     pub expansion: Mark,
@@ -133,13 +134,38 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
     /// Attempts to resolve `ident` in namespaces `ns` of `module`.
     /// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete.
     pub fn resolve_ident_in_module_unadjusted(&mut self,
-                                              module: Module<'a>,
+                                              module: ModuleOrUniformRoot<'a>,
                                               ident: Ident,
                                               ns: Namespace,
                                               restricted_shadowing: bool,
                                               record_used: bool,
                                               path_span: Span)
                                               -> Result<&'a NameBinding<'a>, Determinacy> {
+        let module = match module {
+            ModuleOrUniformRoot::Module(module) => module,
+            ModuleOrUniformRoot::UniformRoot(root) => {
+                let crate_root = if
+                    root != keywords::Extern.name() &&
+                    (
+                        ident.name == keywords::Crate.name() ||
+                        ident.name == keywords::DollarCrate.name()
+                    )
+                {
+                    self.resolve_crate_root(ident)
+                } else if !ident.is_path_segment_keyword() {
+                    let crate_id =
+                        self.crate_loader.process_path_extern(ident.name, ident.span);
+                    self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
+                } else {
+                    return Err(Determined);
+                };
+                self.populate_module_if_necessary(crate_root);
+                let binding = (crate_root, ty::Visibility::Public,
+                               ident.span, Mark::root()).to_name_binding(self.arenas);
+                return Ok(binding);
+            }
+        };
+
         self.populate_module_if_necessary(module);
 
         let resolution = self.resolution(module, ident, ns)
@@ -260,7 +286,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
             if !self.is_accessible(glob_import.vis.get()) {
                 continue
             }
-            let module = unwrap_or!(glob_import.imported_module.get(), return Err(Undetermined));
+            let module = match glob_import.imported_module.get() {
+                Some(ModuleOrUniformRoot::Module(module)) => module,
+                Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
+                None => return Err(Undetermined),
+            };
             let (orig_current_module, mut ident) = (self.current_module, ident.modern());
             match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) {
                 Some(Some(def)) => self.current_module = self.macro_def_scope(def),
@@ -268,7 +298,12 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 None => continue,
             };
             let result = self.resolve_ident_in_module_unadjusted(
-                module, ident, ns, false, false, path_span,
+                ModuleOrUniformRoot::Module(module),
+                ident,
+                ns,
+                false,
+                false,
+                path_span,
             );
             self.current_module = orig_current_module;
             match result {
@@ -576,8 +611,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
-            let result = self.resolve_path(&directive.module_path[..], None, false,
-                                           directive.span, directive.crate_lint());
+            let result = self.resolve_path(
+                Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
+                &directive.module_path[..],
+                None,
+                false,
+                directive.span,
+                directive.crate_lint(),
+            );
             directive.vis.set(vis);
 
             match result {
@@ -644,77 +685,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
         self.current_module = directive.parent;
         let ImportDirective { ref module_path, span, .. } = *directive;
-        let mut warn_if_binding_comes_from_local_crate = false;
-
-        // FIXME: Last path segment is treated specially in import resolution, so extern crate
-        // mode for absolute paths needs some special support for single-segment imports.
-        if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() ||
-                                      module_path[0].name == keywords::Extern.name()) {
-            let is_extern = module_path[0].name == keywords::Extern.name() ||
-                            (self.session.features_untracked().extern_absolute_paths &&
-                             self.session.rust_2018());
-            match directive.subclass {
-                GlobImport { .. } if is_extern => {
-                    return Some((directive.span,
-                                 "cannot glob-import all possible crates".to_string()));
-                }
-                GlobImport { .. } if self.session.features_untracked().extern_absolute_paths => {
-                    self.lint_path_starts_with_module(
-                        directive.root_id,
-                        directive.root_span,
-                    );
-                }
-                SingleImport { source, target, .. } => {
-                    let crate_root = if source.name == keywords::Crate.name() &&
-                                        module_path[0].name != keywords::Extern.name() {
-                        if target.name == keywords::Crate.name() {
-                            return Some((directive.span,
-                                         "crate root imports need to be explicitly named: \
-                                          `use crate as name;`".to_string()));
-                        } else {
-                            Some(self.resolve_crate_root(source))
-                        }
-                    } else if is_extern && !source.is_path_segment_keyword() {
-                        let crate_id =
-                            self.resolver.crate_loader.process_use_extern(
-                                source.name,
-                                directive.span,
-                                directive.id,
-                                &self.resolver.definitions,
-                            );
-                        let crate_root =
-                            self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
-                        self.populate_module_if_necessary(crate_root);
-                        Some(crate_root)
-                    } else {
-                        warn_if_binding_comes_from_local_crate = true;
-                        None
-                    };
-
-                    if let Some(crate_root) = crate_root {
-                        let binding = (crate_root, ty::Visibility::Public, directive.span,
-                                       directive.expansion).to_name_binding(self.arenas);
-                        let binding = self.arenas.alloc_name_binding(NameBinding {
-                            kind: NameBindingKind::Import {
-                                binding,
-                                directive,
-                                used: Cell::new(false),
-                            },
-                            vis: directive.vis.get(),
-                            span: directive.span,
-                            expansion: directive.expansion,
-                        });
-                        let _ = self.try_define(directive.parent, target, TypeNS, binding);
-                        let import = self.import_map.entry(directive.id).or_default();
-                        import[TypeNS] = Some(PathResolution::new(binding.def()));
-                        return None;
-                    }
-                }
-                _ => {}
-            }
-        }
 
         let module_result = self.resolve_path(
+            Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
             &module_path,
             None,
             true,
@@ -734,7 +707,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 if !self_path.is_empty() && !is_special(self_path[0]) &&
                    !(self_path.len() > 1 && is_special(self_path[1])) {
                     self_path[0].name = keywords::SelfValue.name();
-                    self_result = Some(self.resolve_path(&self_path, None, false,
+                    self_result = Some(self.resolve_path(None, &self_path, None, false,
                                                          span, CrateLint::No));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
@@ -748,12 +721,27 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
 
         let (ident, result, type_ns_only) = match directive.subclass {
             SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only),
-            GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
-                // Importing a module into itself is not allowed.
-                return Some((directive.span,
-                             "Cannot glob-import a module into itself.".to_string()));
-            }
             GlobImport { is_prelude, ref max_vis } => {
+                if module_path.len() <= 1 {
+                    // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
+                    // 2 segments, so the `resolve_path` above won't trigger it.
+                    let mut full_path = module_path.clone();
+                    full_path.push(keywords::Invalid.ident());
+                    self.lint_if_path_starts_with_module(
+                        directive.crate_lint(),
+                        &full_path,
+                        directive.span,
+                        None,
+                    );
+                }
+
+                if let ModuleOrUniformRoot::Module(module) = module {
+                    if module.def_id() == directive.parent.def_id() {
+                        // Importing a module into itself is not allowed.
+                        return Some((directive.span,
+                            "Cannot glob-import a module into itself.".to_string()));
+                    }
+                }
                 if !is_prelude &&
                    max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
                    !max_vis.get().is_at_least(directive.vis.get(), &*self) {
@@ -770,8 +758,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
             if let Ok(binding) = result[ns].get() {
                 all_ns_err = false;
                 if this.record_use(ident, ns, binding, directive.span) {
-                    this.resolution(module, ident, ns).borrow_mut().binding =
-                        Some(this.dummy_binding);
+                    if let ModuleOrUniformRoot::Module(module) = module {
+                        this.resolution(module, ident, ns).borrow_mut().binding =
+                            Some(this.dummy_binding);
+                    }
                 }
             }
         });
@@ -786,8 +776,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
             });
 
             return if all_ns_failed {
-                let resolutions = module.resolutions.borrow();
-                let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
+                let resolutions = match module {
+                    ModuleOrUniformRoot::Module(module) =>
+                        Some(module.resolutions.borrow()),
+                    ModuleOrUniformRoot::UniformRoot(_) => None,
+                };
+                let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
+                let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
                     if *i == ident { return None; } // Never suggest the same name
                     match *resolution.borrow() {
                         NameResolution { binding: Some(name_binding), .. } => {
@@ -813,11 +808,24 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                         Some(name) => format!(". Did you mean to use `{}`?", name),
                         None => "".to_owned(),
                     };
-                let module_str = module_to_string(module);
-                let msg = if let Some(module_str) = module_str {
-                    format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
-                } else {
-                    format!("no `{}` in the root{}", ident, lev_suggestion)
+                let msg = match module {
+                    ModuleOrUniformRoot::Module(module) => {
+                        let module_str = module_to_string(module);
+                        if let Some(module_str) = module_str {
+                            format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
+                        } else {
+                            format!("no `{}` in the root{}", ident, lev_suggestion)
+                        }
+                    }
+                    ModuleOrUniformRoot::UniformRoot(_) => {
+                        if !ident.is_path_segment_keyword() {
+                            format!("no `{}` external crate{}", ident, lev_suggestion)
+                        } else {
+                            // HACK(eddyb) this shows up for `self` & `super`, which
+                            // should work instead - for now keep the same error message.
+                            format!("no `{}` in the root{}", ident, lev_suggestion)
+                        }
+                    }
                 };
                 Some((span, msg))
             } else {
@@ -868,26 +876,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
             }
         }
 
-        if warn_if_binding_comes_from_local_crate {
-            let mut warned = false;
+        if module_path.len() <= 1 {
+            // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
+            // 2 segments, so the `resolve_path` above won't trigger it.
+            let mut full_path = module_path.clone();
+            full_path.push(ident);
             self.per_ns(|this, ns| {
-                let binding = match result[ns].get().ok() {
-                    Some(b) => b,
-                    None => return
-                };
-                if let NameBindingKind::Import { directive: d, .. } = binding.kind {
-                    if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
-                        return
-                    }
-                }
-                if warned {
-                    return
+                if let Ok(binding) = result[ns].get() {
+                    this.lint_if_path_starts_with_module(
+                        directive.crate_lint(),
+                        &full_path,
+                        directive.span,
+                        Some(binding),
+                    );
                 }
-                warned = true;
-                this.lint_path_starts_with_module(
-                    directive.root_id,
-                    directive.root_span,
-                );
             });
         }
 
@@ -904,7 +906,15 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     }
 
     fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
-        let module = directive.imported_module.get().unwrap();
+        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");
+                return;
+            }
+        };
+
         self.populate_module_if_necessary(module);
 
         if let Some(Def::Trait(_)) = module.def() {
@@ -1026,8 +1036,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                             };
                             let mut err = self.session.struct_span_err(binding.span, &msg);
 
-                            let imported_module = directive.imported_module.get()
-                                .expect("module should exist");
+                            let imported_module = match directive.imported_module.get() {
+                                Some(ModuleOrUniformRoot::Module(module)) => module,
+                                _ => bug!("module should exist"),
+                            };
                             let resolutions = imported_module.parent.expect("parent should exist")
                                 .resolutions.borrow();
                             let enum_path_segment_index = directive.module_path.len() - 1;
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 6925ed2afb8..b66946affad 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -101,7 +101,7 @@ impl Path {
     // or starts with something like `self`/`super`/`$crate`/etc.
     pub fn make_root(&self) -> Option<PathSegment> {
         if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) {
-            if ident.is_path_segment_keyword() && ident.name != keywords::Crate.name() {
+            if ident.is_path_segment_keyword() {
                 return None;
             }
         }
diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs
index 70597a230a8..4a667f020ad 100644
--- a/src/test/compile-fail/dollar-crate-is-keyword.rs
+++ b/src/test/compile-fail/dollar-crate-is-keyword.rs
@@ -10,7 +10,11 @@
 
 macro_rules! m {
     () => {
-        struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
+        // Avoid having more than one `$crate`-named item in the same module,
+        // as even though they error, they still parse as `$crate` and conflict.
+        mod foo {
+            struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
+        }
 
         use $crate; // OK
                     //~^ WARN `$crate` may not be imported
diff --git a/src/test/compile-fail/import-crate-var.rs b/src/test/compile-fail/import-crate-var.rs
index e58ba2c8891..b09883d9ade 100644
--- a/src/test/compile-fail/import-crate-var.rs
+++ b/src/test/compile-fail/import-crate-var.rs
@@ -9,15 +9,14 @@
 // except according to those terms.
 
 // aux-build:import_crate_var.rs
-// error-pattern: `$crate` may not be imported
-// error-pattern: `use $crate;` was erroneously allowed and will become a hard error
-// error-pattern: compilation successful
 
 #![feature(rustc_attrs)]
 
 #[macro_use] extern crate import_crate_var;
 
 #[rustc_error]
-fn main() {
+fn main() { //~ ERROR compilation successful
     m!();
+    //~^ WARN `$crate` may not be imported
+    //~| NOTE `use $crate;` was erroneously allowed and will become a hard error
 }
diff --git a/src/test/compile-fail/keyword-extern-as-identifier.rs b/src/test/compile-fail/keyword-extern-as-identifier.rs
index e5927d09b41..3e445853957 100644
--- a/src/test/compile-fail/keyword-extern-as-identifier.rs
+++ b/src/test/compile-fail/keyword-extern-as-identifier.rs
@@ -11,5 +11,5 @@
 #![feature(extern_in_paths)]
 
 fn main() {
-    let extern = 0; //~ ERROR expected unit struct/variant or constant, found module `extern`
+    let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
 }
diff --git a/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs b/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs
index e9de0f01b30..69fc4b4f7f8 100644
--- a/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs
+++ b/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs
@@ -11,10 +11,8 @@
 // aux-build:xcrate.rs
 // edition:2018
 
-use crate; //~ ERROR unresolved import `crate`
-           //~^ NOTE crate root imports need to be explicitly named: `use crate as name;`
-use *; //~ ERROR unresolved import `*`
-       //~^ NOTE cannot glob-import all possible crates
+use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
+use *; //~ ERROR cannot glob-import all possible crates
 
 fn main() {
     let s = ::xcrate; //~ ERROR expected value, found module `xcrate`
diff --git a/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs b/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs
index ebc42aa9d44..017844a0252 100644
--- a/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs
+++ b/src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs
@@ -14,8 +14,7 @@
 
 use extern; //~ ERROR unresolved import `extern`
             //~^ NOTE no `extern` in the root
-use extern::*; //~ ERROR unresolved import `extern::*`
-               //~^ NOTE cannot glob-import all possible crates
+use extern::*; //~ ERROR cannot glob-import all possible crates
 
 fn main() {
     let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
diff --git a/src/test/run-pass/issue-52140/auxiliary/some_crate.rs b/src/test/run-pass/issue-52140/auxiliary/some_crate.rs
new file mode 100644
index 00000000000..bf8dee0863a
--- /dev/null
+++ b/src/test/run-pass/issue-52140/auxiliary/some_crate.rs
@@ -0,0 +1,15 @@
+// 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.
+
+#![crate_type = "lib"]
+
+pub fn hello() {
+    println!("Hello, world!");
+}
diff --git a/src/test/run-pass/issue-52140/main.rs b/src/test/run-pass/issue-52140/main.rs
new file mode 100644
index 00000000000..6fae6adc442
--- /dev/null
+++ b/src/test/run-pass/issue-52140/main.rs
@@ -0,0 +1,21 @@
+// 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.
+
+// aux-build:some_crate.rs
+// edition:2018
+
+mod foo {
+    pub use some_crate;
+}
+
+fn main() {
+    ::some_crate::hello();
+    foo::some_crate::hello();
+}
diff --git a/src/test/run-pass/issue-52141/auxiliary/some_crate.rs b/src/test/run-pass/issue-52141/auxiliary/some_crate.rs
new file mode 100644
index 00000000000..bf8dee0863a
--- /dev/null
+++ b/src/test/run-pass/issue-52141/auxiliary/some_crate.rs
@@ -0,0 +1,15 @@
+// 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.
+
+#![crate_type = "lib"]
+
+pub fn hello() {
+    println!("Hello, world!");
+}
diff --git a/src/test/run-pass/issue-52141/main.rs b/src/test/run-pass/issue-52141/main.rs
new file mode 100644
index 00000000000..8f3fc9f9698
--- /dev/null
+++ b/src/test/run-pass/issue-52141/main.rs
@@ -0,0 +1,24 @@
+// 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.
+
+// aux-build:some_crate.rs
+// edition:2018
+
+use some_crate as some_name;
+
+mod foo {
+    pub use crate::some_name::*;
+}
+
+fn main() {
+    ::some_crate::hello();
+    some_name::hello();
+    foo::hello();
+}
diff --git a/src/test/run-pass/issue-52705/auxiliary/png.rs b/src/test/run-pass/issue-52705/auxiliary/png.rs
new file mode 100644
index 00000000000..48d53a2cbac
--- /dev/null
+++ b/src/test/run-pass/issue-52705/auxiliary/png.rs
@@ -0,0 +1,13 @@
+// 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.
+
+#![crate_type = "lib"]
+
+pub struct DecodingError;
diff --git a/src/test/run-pass/issue-52705/main.rs b/src/test/run-pass/issue-52705/main.rs
new file mode 100644
index 00000000000..101f67e3e7b
--- /dev/null
+++ b/src/test/run-pass/issue-52705/main.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// aux-build:png.rs
+// edition:2018
+
+mod png {
+    use png as png_ext;
+
+    fn foo() -> png_ext::DecodingError { unimplemented!() }
+}
+
+fn main() {
+    println!("Hello, world!");
+}