Skip to content

Commit d1862b4

Browse files
committed
resolve: Fallback to extern prelude in 2015 imports used from global 2018 edition
1 parent 5e12175 commit d1862b4

8 files changed

+86
-25
lines changed

src/librustc_resolve/lib.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ enum Weak {
104104

105105
enum ScopeSet {
106106
Import(Namespace),
107+
AbsolutePath(Namespace),
107108
Macro(MacroKind),
108109
Module,
109110
}
@@ -1008,6 +1009,9 @@ enum ModuleOrUniformRoot<'a> {
10081009
/// Regular module.
10091010
Module(Module<'a>),
10101011

1012+
/// Virtual module that denotes resolution in crate root with fallback to extern prelude.
1013+
CrateRootAndExternPrelude,
1014+
10111015
/// Virtual module that denotes resolution in extern prelude.
10121016
/// Used for paths starting with `::` on 2018 edition or `extern::`.
10131017
ExternPrelude,
@@ -1021,9 +1025,11 @@ enum ModuleOrUniformRoot<'a> {
10211025
impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
10221026
fn eq(&self, other: &Self) -> bool {
10231027
match (*self, *other) {
1024-
(ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
1025-
ptr::eq(lhs, rhs),
1026-
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true,
1028+
(ModuleOrUniformRoot::Module(lhs),
1029+
ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs),
1030+
(ModuleOrUniformRoot::CrateRootAndExternPrelude,
1031+
ModuleOrUniformRoot::CrateRootAndExternPrelude) |
1032+
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
10271033
(ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
10281034
_ => false,
10291035
}
@@ -1243,6 +1249,7 @@ struct UseError<'a> {
12431249
#[derive(Clone, Copy, PartialEq, Debug)]
12441250
enum AmbiguityKind {
12451251
Import,
1252+
AbsolutePath,
12461253
BuiltinAttr,
12471254
DeriveHelper,
12481255
LegacyHelperVsPrelude,
@@ -1258,6 +1265,8 @@ impl AmbiguityKind {
12581265
match self {
12591266
AmbiguityKind::Import =>
12601267
"name vs any other name during import resolution",
1268+
AmbiguityKind::AbsolutePath =>
1269+
"name in the crate root vs extern crate during absolute path resolution",
12611270
AmbiguityKind::BuiltinAttr =>
12621271
"built-in attribute vs any other name",
12631272
AmbiguityKind::DeriveHelper =>
@@ -2226,6 +2235,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
22262235
ident.span = ident.span.modern();
22272236
ident.span.adjust(Mark::root());
22282237
}
2238+
ModuleOrUniformRoot::CrateRootAndExternPrelude |
22292239
ModuleOrUniformRoot::CurrentScope => {
22302240
// No adjustments
22312241
}
@@ -3791,6 +3801,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
37913801
module = Some(ModuleOrUniformRoot::ExternPrelude);
37923802
continue;
37933803
}
3804+
if name == keywords::CrateRoot.name() &&
3805+
ident.span.rust_2015() && self.session.rust_2018() {
3806+
// `::a::b` from 2015 macro on 2018 global edition
3807+
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
3808+
continue;
3809+
}
37943810
if name == keywords::CrateRoot.name() ||
37953811
name == keywords::Crate.name() ||
37963812
name == keywords::DollarCrate.name() {

src/librustc_resolve/macros.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -625,13 +625,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
625625

626626
// Go through all the scopes and try to resolve the name.
627627
let rust_2015 = orig_ident.span.rust_2015();
628-
let (ns, macro_kind, is_import) = match scope_set {
629-
ScopeSet::Import(ns) => (ns, None, true),
630-
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
631-
ScopeSet::Module => (TypeNS, None, false),
628+
let (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
629+
ScopeSet::Import(ns) => (ns, None, true, false),
630+
ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
631+
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
632+
ScopeSet::Module => (TypeNS, None, false, false),
632633
};
633634
let mut where_to_resolve = match ns {
634-
_ if is_import && rust_2015 => WhereToResolve::CrateRoot,
635+
_ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot,
635636
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
636637
MacroNS => WhereToResolve::DeriveHelpers,
637638
};
@@ -761,7 +762,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
761762
}
762763
}
763764
WhereToResolve::ExternPrelude => {
764-
if use_prelude {
765+
if use_prelude || is_absolute_path {
765766
match self.extern_prelude_get(ident, !record_used) {
766767
Some(binding) => Ok((binding, Flags::PRELUDE)),
767768
None => Err(Determinacy::determined(
@@ -827,6 +828,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
827828

828829
let ambiguity_error_kind = if is_import {
829830
Some(AmbiguityKind::Import)
831+
} else if is_absolute_path {
832+
Some(AmbiguityKind::AbsolutePath)
830833
} else if innermost_def == builtin || def == builtin {
831834
Some(AmbiguityKind::BuiltinAttr)
832835
} else if innermost_def == derive_helper || def == derive_helper {
@@ -894,10 +897,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
894897
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
895898
LegacyScope::Uninitialized => unreachable!(),
896899
}
897-
WhereToResolve::CrateRoot => match ns {
900+
WhereToResolve::CrateRoot if is_import => match ns {
898901
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
899902
MacroNS => WhereToResolve::DeriveHelpers,
900903
}
904+
WhereToResolve::CrateRoot if is_absolute_path => match ns {
905+
TypeNS => {
906+
ident.span.adjust(Mark::root());
907+
WhereToResolve::ExternPrelude
908+
}
909+
ValueNS | MacroNS => break,
910+
}
911+
WhereToResolve::CrateRoot => unreachable!(),
901912
WhereToResolve::Module(module) => {
902913
match self.hygienic_lexical_parent(module, &mut ident.span) {
903914
Some(parent_module) => WhereToResolve::Module(parent_module),
@@ -915,6 +926,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
915926
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
916927
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
917928
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
929+
WhereToResolve::ExternPrelude if is_absolute_path => break,
918930
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
919931
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
920932
WhereToResolve::StdLibPrelude => match ns {

src/librustc_resolve/resolve_imports.rs

+9
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
162162
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
163163
let module = match module {
164164
ModuleOrUniformRoot::Module(module) => module,
165+
ModuleOrUniformRoot::CrateRootAndExternPrelude => {
166+
assert!(!restricted_shadowing);
167+
let parent_scope = self.dummy_parent_scope();
168+
let binding = self.early_resolve_ident_in_lexical_scope(
169+
ident, ScopeSet::AbsolutePath(ns), &parent_scope,
170+
record_used, record_used, path_span,
171+
);
172+
return binding.map_err(|determinacy| (determinacy, Weak::No));
173+
}
165174
ModuleOrUniformRoot::ExternPrelude => {
166175
assert!(!restricted_shadowing);
167176
return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {

src/test/ui/editions/auxiliary/edition-imports-2015.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ macro_rules! gen_imports { () => {
77

88
fn check_absolute() {
99
::absolute::Path;
10-
// ::std::collections::LinkedList::<u8>::new(); // FIXME
10+
::std::collections::LinkedList::<u8>::new();
1111
}
1212
}}
1313

@@ -27,4 +27,5 @@ macro_rules! gen_gated { () => {
2727
#[macro_export]
2828
macro_rules! gen_ambiguous { () => {
2929
use Ambiguous;
30+
type A = ::edition_imports_2015::Path;
3031
}}

src/test/ui/editions/edition-imports-2018.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// compile-pass
21
// edition:2018
32
// aux-build:edition-imports-2015.rs
43

@@ -22,12 +21,7 @@ mod check {
2221
}
2322

2423
mod check_glob {
25-
gen_glob!(); // OK
26-
27-
fn check() {
28-
import::Path;
29-
absolute::Path;
30-
}
24+
gen_glob!(); //~ ERROR cannot glob-import all possible crates
3125
}
3226

3327
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: cannot glob-import all possible crates
2+
--> $DIR/edition-imports-2018.rs:24:5
3+
|
4+
LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates
5+
| ^^^^^^^^^^^^
6+
|
7+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
8+
9+
error: aborting due to previous error
10+

src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
// edition:2018
2+
// compile-flags:--extern edition_imports_2015
23
// aux-build:edition-imports-2015.rs
34
// error-pattern: `Ambiguous` is ambiguous
5+
// error-pattern: `edition_imports_2015` is ambiguous
46

5-
#[macro_use]
6-
extern crate edition_imports_2015;
7+
mod edition_imports_2015 {
8+
pub struct Path;
9+
}
710

811
pub struct Ambiguous {}
912

1013
mod check {
1114
pub struct Ambiguous {}
1215

1316
fn check() {
14-
gen_ambiguous!();
17+
edition_imports_2015::gen_ambiguous!();
1518
}
1619
}
1720

Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
11
error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution)
22
--> <::edition_imports_2015::gen_ambiguous macros>:1:15
33
|
4-
LL | ( ) => { use Ambiguous ; }
4+
LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; }
55
| ^^^^^^^^^ ambiguous name
66
|
77
note: `Ambiguous` could refer to the struct defined here
8-
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1
8+
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1
99
|
1010
LL | pub struct Ambiguous {}
1111
| ^^^^^^^^^^^^^^^^^^^^^^^
1212
note: `Ambiguous` could also refer to the struct defined here
13-
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5
13+
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5
1414
|
1515
LL | pub struct Ambiguous {}
1616
| ^^^^^^^^^^^^^^^^^^^^^^^
1717
= help: use `self::Ambiguous` to refer to this struct unambiguously
1818

19-
error: aborting due to previous error
19+
error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution)
20+
--> <::edition_imports_2015::gen_ambiguous macros>:1:39
21+
|
22+
LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; }
23+
| ^^^^^^^^^^^^^^^^^^^^ ambiguous name
24+
|
25+
= note: `edition_imports_2015` could refer to an extern crate passed with `--extern`
26+
= help: use `::edition_imports_2015` to refer to this extern crate unambiguously
27+
note: `edition_imports_2015` could also refer to the module defined here
28+
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1
29+
|
30+
LL | / mod edition_imports_2015 {
31+
LL | | pub struct Path;
32+
LL | | }
33+
| |_^
34+
35+
error: aborting due to 2 previous errors
2036

2137
For more information about this error, try `rustc --explain E0659`.

0 commit comments

Comments
 (0)