diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index bc0e8a56157..0be9881f910 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -104,6 +104,7 @@ enum Weak { enum ScopeSet { Import(Namespace), + AbsolutePath(Namespace), Macro(MacroKind), Module, } @@ -1008,6 +1009,9 @@ enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), + /// 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, @@ -1021,9 +1025,11 @@ enum ModuleOrUniformRoot<'a> { 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::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true, + (ModuleOrUniformRoot::Module(lhs), + ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), + (ModuleOrUniformRoot::CrateRootAndExternPrelude, + ModuleOrUniformRoot::CrateRootAndExternPrelude) | + (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, _ => false, } @@ -1243,6 +1249,7 @@ struct UseError<'a> { #[derive(Clone, Copy, PartialEq, Debug)] enum AmbiguityKind { Import, + AbsolutePath, BuiltinAttr, DeriveHelper, LegacyHelperVsPrelude, @@ -1258,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 => @@ -2226,6 +2235,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } + ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => { // No adjustments } @@ -3791,6 +3801,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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() || name == keywords::Crate.name() || name == keywords::DollarCrate.name() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5493913fd81..d306e9ebe32 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -625,13 +625,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Go through all the scopes and try to resolve the name. let rust_2015 = orig_ident.span.rust_2015(); - let (ns, macro_kind, is_import) = match scope_set { - ScopeSet::Import(ns) => (ns, None, true), - ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), - ScopeSet::Module => (TypeNS, None, false), + 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_import && rust_2015 => WhereToResolve::CrateRoot, + _ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot, TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), MacroNS => WhereToResolve::DeriveHelpers, }; @@ -761,7 +762,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( @@ -827,6 +828,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 { @@ -894,10 +897,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), LegacyScope::Uninitialized => unreachable!(), } - WhereToResolve::CrateRoot => match ns { + 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), @@ -915,6 +926,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 { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 47bfadf932e..3bfa862f0dc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -162,6 +162,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, + ModuleOrUniformRoot::CrateRootAndExternPrelude => { + assert!(!restricted_shadowing); + let parent_scope = self.dummy_parent_scope(); + let binding = self.early_resolve_ident_in_lexical_scope( + ident, ScopeSet::AbsolutePath(ns), &parent_scope, + 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) { diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs index d7985d12dae..c72331ca2e1 100644 --- a/src/test/ui/editions/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -7,7 +7,7 @@ macro_rules! gen_imports { () => { fn check_absolute() { ::absolute::Path; - // ::std::collections::LinkedList::::new(); // FIXME + ::std::collections::LinkedList::::new(); } }} @@ -27,4 +27,5 @@ macro_rules! gen_gated { () => { #[macro_export] macro_rules! gen_ambiguous { () => { use Ambiguous; + type A = ::edition_imports_2015::Path; }} diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs index 989170d041f..dcdbf0d050b 100644 --- a/src/test/ui/editions/edition-imports-2018.rs +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -1,4 +1,3 @@ -// compile-pass // edition:2018 // aux-build:edition-imports-2015.rs @@ -22,12 +21,7 @@ mod check { } mod check_glob { - gen_glob!(); // OK - - fn check() { - import::Path; - absolute::Path; - } + 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 00000000000..944f42ee045 --- /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 index 2527b30f07b..562d3c9e70f 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,9 +1,12 @@ // edition:2018 +// compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs // error-pattern: `Ambiguous` is ambiguous +// error-pattern: `edition_imports_2015` is ambiguous -#[macro_use] -extern crate edition_imports_2015; +mod edition_imports_2015 { + pub struct Path; +} pub struct Ambiguous {} @@ -11,7 +14,7 @@ mod check { pub struct Ambiguous {} fn check() { - gen_ambiguous!(); + edition_imports_2015::gen_ambiguous!(); } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr index 8e0b135121e..d0897d081c3 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -1,21 +1,37 @@ error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) --> <::edition_imports_2015::gen_ambiguous macros>:1:15 | -LL | ( ) => { use Ambiguous ; } +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } | ^^^^^^^^^ ambiguous name | note: `Ambiguous` could refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: `Ambiguous` could also refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::Ambiguous` to refer to this struct unambiguously -error: aborting due to previous error +error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution) + --> <::edition_imports_2015::gen_ambiguous macros>:1:39 + | +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } + | ^^^^^^^^^^^^^^^^^^^^ ambiguous name + | + = note: `edition_imports_2015` could refer to an extern crate passed with `--extern` + = help: use `::edition_imports_2015` to refer to this extern crate unambiguously +note: `edition_imports_2015` could also refer to the module defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1 + | +LL | / mod edition_imports_2015 { +LL | | pub struct Path; +LL | | } + | |_^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`.