Skip to content

Commit 29640c5

Browse files
committed
Auto merge of #57745 - petrochenkov:uni2015, r=<try>
[WIP] resolve: Fallback to extern crates in absolute paths on 2015 edition TODO: Run crater, fix diagnostics This PR changes the resolution scheme for imports and absolute paths from | Local edition | Global edition | Imports (`use foo;`) | Absolute paths (`::foo`) | | ------------- |----------------|-----------------------------------------|------------------------------------------------| | 2018 | Any | Uniform | Extern prelude | | 2015 | 2015 | Crate-relative | Crate-relative | | 2015 | 2018 | Crate-relative with fallback to Uniform | Crate-relative with fallback to Extern prelude | (which was introduced in #56053) to | Local edition | Global edition | Imports (`use foo;`) | Absolute paths (`::foo`) | | ------------- |----------------|-----------------------------------------|------------------------------------------------| | 2018 | Any | Uniform | Extern prelude | | 2015 | Any | Crate-relative with fallback to Extern prelude | Crate-relative with fallback to Extern prelude | (with `use foo;` still desugaring into `use ::foo;` on 2015 edition). This way we - Get rid of the special case "2015 macro used on 2018 edition". - Resolve the issue discussed in #55478, i.e. "on 2015 edition you don't need `extern crate` until you need `use`, then you need `extern crate`". With this change `use my_crate::foo` and `let x = ::my_crate::foo` work without needing `extern crate` consistently with `let x = my_crate::foo`. r? @Centril
2 parents f613dc1 + bd4a554 commit 29640c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+102
-199
lines changed

src/librustc_resolve/build_reduced_graph.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ impl<'a> Resolver<'a> {
129129
// get crate root prepended, but get special treatment during in-scope resolution instead.
130130
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
131131
let crate_root = match prefix_iter.peek() {
132-
Some(seg) if !seg.ident.is_path_segment_keyword() &&
133-
seg.ident.span.rust_2015() && self.session.rust_2015() => {
132+
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
134133
Some(seg.ident.span.ctxt())
135134
}
136135
None if is_glob && use_tree.span.rust_2015() => {

src/librustc_resolve/lib.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ struct UseError<'a> {
12431243
#[derive(Clone, Copy, PartialEq, Debug)]
12441244
enum AmbiguityKind {
12451245
Import,
1246-
AbsolutePath,
1246+
// AbsolutePath,
12471247
BuiltinAttr,
12481248
DeriveHelper,
12491249
LegacyHelperVsPrelude,
@@ -1259,8 +1259,8 @@ impl AmbiguityKind {
12591259
match self {
12601260
AmbiguityKind::Import =>
12611261
"name vs any other name during import resolution",
1262-
AmbiguityKind::AbsolutePath =>
1263-
"name in the crate root vs extern crate during absolute path resolution",
1262+
// AmbiguityKind::AbsolutePath =>
1263+
// "name in the crate root vs extern crate during absolute path resolution",
12641264
AmbiguityKind::BuiltinAttr =>
12651265
"built-in attribute vs any other name",
12661266
AmbiguityKind::DeriveHelper =>
@@ -1513,6 +1513,8 @@ pub struct Resolver<'a> {
15131513
/// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
15141514
/// We are resolving a last import segment during import validation.
15151515
last_import_segment: bool,
1516+
/// We are resolving a prefix for `use *` or `use ::*` on 2015 edition.
1517+
root_glob_import: bool,
15161518
/// This binding should be ignored during in-module resolution, so that we don't get
15171519
/// "self-confirming" import resolutions during import validation.
15181520
blacklisted_binding: Option<&'a NameBinding<'a>>,
@@ -1861,6 +1863,7 @@ impl<'a> Resolver<'a> {
18611863
current_self_type: None,
18621864
current_self_item: None,
18631865
last_import_segment: false,
1866+
root_glob_import: false,
18641867
blacklisted_binding: None,
18651868

18661869
primitive_type_table: PrimitiveTypeTable::new(),
@@ -3833,19 +3836,17 @@ impl<'a> Resolver<'a> {
38333836
self.resolve_self(&mut ctxt, self.current_module)));
38343837
continue;
38353838
}
3836-
if name == keywords::PathRoot.name() && ident.span.rust_2018() {
3837-
module = Some(ModuleOrUniformRoot::ExternPrelude);
3838-
continue;
3839-
}
3840-
if name == keywords::PathRoot.name() &&
3841-
ident.span.rust_2015() && self.session.rust_2018() {
3842-
// `::a::b` from 2015 macro on 2018 global edition
3843-
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
3839+
if name == keywords::PathRoot.name() {
3840+
module = Some(if ident.span.rust_2018() {
3841+
ModuleOrUniformRoot::ExternPrelude
3842+
} else if !self.root_glob_import {
3843+
ModuleOrUniformRoot::CrateRootAndExternPrelude
3844+
} else {
3845+
ModuleOrUniformRoot::Module(self.resolve_crate_root(ident))
3846+
});
38443847
continue;
38453848
}
3846-
if name == keywords::PathRoot.name() ||
3847-
name == keywords::Crate.name() ||
3848-
name == keywords::DollarCrate.name() {
3849+
if name == keywords::Crate.name() || name == keywords::DollarCrate.name() {
38493850
// `::a::b`, `crate::a::b` or `$crate::a::b`
38503851
module = Some(ModuleOrUniformRoot::Module(
38513852
self.resolve_crate_root(ident)));

src/librustc_resolve/macros.rs

+1-40
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,6 @@ impl<'a> Resolver<'a> {
709709

710710
let ambiguity_error_kind = if is_import {
711711
Some(AmbiguityKind::Import)
712-
} else if is_absolute_path {
713-
Some(AmbiguityKind::AbsolutePath)
714712
} else if innermost_def == builtin || def == builtin {
715713
Some(AmbiguityKind::BuiltinAttr)
716714
} else if innermost_def == derive_helper || def == derive_helper {
@@ -824,44 +822,7 @@ impl<'a> Resolver<'a> {
824822
}
825823

826824
// The first found solution was the only one, return it.
827-
if let Some((binding, flags)) = innermost_result {
828-
// We get to here only if there's no ambiguity, in ambiguous cases an error will
829-
// be reported anyway, so there's no reason to report an additional feature error.
830-
// The `binding` can actually be introduced by something other than `--extern`,
831-
// but its `Def` should coincide with a crate passed with `--extern`
832-
// (otherwise there would be ambiguity) and we can skip feature error in this case.
833-
'ok: {
834-
if !is_import || !rust_2015 {
835-
break 'ok;
836-
}
837-
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
838-
break 'ok;
839-
}
840-
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
841-
let root_module = self.resolve_crate_root(root_ident);
842-
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
843-
orig_ident, ns, None, false, path_span)
844-
.is_ok() {
845-
break 'ok;
846-
}
847-
848-
let msg = "imports can only refer to extern crate names passed with \
849-
`--extern` in macros originating from 2015 edition";
850-
let mut err = self.session.struct_span_err(ident.span, msg);
851-
let what = self.binding_description(binding, ident,
852-
flags.contains(Flags::MISC_FROM_PRELUDE));
853-
let note_msg = format!("this import refers to {what}", what = what);
854-
let label_span = if binding.span.is_dummy() {
855-
err.note(&note_msg);
856-
ident.span
857-
} else {
858-
err.span_note(binding.span, &note_msg);
859-
binding.span
860-
};
861-
err.span_label(label_span, "not an extern crate passed with `--extern`");
862-
err.emit();
863-
}
864-
825+
if let Some((binding, _)) = innermost_result {
865826
return Ok(binding);
866827
}
867828

src/librustc_resolve/resolve_imports.rs

+8
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
765765
} else {
766766
// For better failure detection, pretend that the import will
767767
// not define any names while resolving its module path.
768+
let orig_root_glob_import = mem::replace(
769+
&mut self.root_glob_import, directive.is_glob() && directive.module_path.len() == 1
770+
);
768771
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
769772
let path_res = self.resolve_path(
770773
&directive.module_path,
@@ -775,6 +778,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
775778
directive.crate_lint(),
776779
);
777780
directive.vis.set(orig_vis);
781+
self.root_glob_import = orig_root_glob_import;
778782

779783
match path_res {
780784
PathResult::Module(module) => module,
@@ -850,12 +854,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
850854
) -> Option<(Span, String, Option<String>)> {
851855
self.current_module = directive.parent_scope.module;
852856

857+
let orig_root_glob_import = mem::replace(
858+
&mut self.root_glob_import, directive.is_glob() && directive.module_path.len() == 1
859+
);
853860
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
854861
let prev_ambiguity_errors_len = self.ambiguity_errors.len();
855862
let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope,
856863
true, directive.span, directive.crate_lint());
857864
let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
858865
directive.vis.set(orig_vis);
866+
self.root_glob_import = orig_root_glob_import;
859867
let module = match path_res {
860868
PathResult::Module(module) => {
861869
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.

src/test/run-make-fulldeps/extern-prelude/Makefile

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ all:
77
$(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
88
$(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
99
$(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
10-
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
11-
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"
10+
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib

src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ error[E0432]: unresolved import `Foo`
22
--> $DIR/issue-38054-do-not-show-unresolved-names.rs:1:5
33
|
44
LL | use Foo; //~ ERROR unresolved
5-
| ^^^ no `Foo` in the root
5+
| ^^^ no `Foo` external crate
66

77
error[E0432]: unresolved import `Foo1`
88
--> $DIR/issue-38054-do-not-show-unresolved-names.rs:3:5
99
|
1010
LL | use Foo1; //~ ERROR unresolved
11-
| ^^^^ no `Foo1` in the root
11+
| ^^^^ no `Foo1` external crate
1212

1313
error: aborting due to 2 previous errors
1414

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-pass
12
// edition:2018
23
// aux-build:edition-imports-2015.rs
34

@@ -21,7 +22,7 @@ mod check {
2122
}
2223

2324
mod check_glob {
24-
gen_glob!(); //~ ERROR cannot glob-import all possible crates
25+
gen_glob!(); // OK
2526
}
2627

2728
fn main() {}

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

-10
This file was deleted.

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-pass
12
// edition:2018
23
// compile-flags:--extern edition_imports_2015
34
// aux-build:edition-imports-2015.rs
@@ -12,8 +13,7 @@ mod check {
1213
pub struct Ambiguous {}
1314

1415
fn check() {
15-
edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
16-
//~| ERROR `edition_imports_2015` is ambiguous
16+
edition_imports_2015::gen_ambiguous!();
1717
}
1818
}
1919

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

-40
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
// edition:2018
22
// aux-build:edition-imports-2015.rs
3-
// error-pattern: imports can only refer to extern crate names passed with `--extern`
43

54
#[macro_use]
65
extern crate edition_imports_2015;
76

87
mod check {
9-
gen_gated!();
8+
gen_gated!(); //~ ERROR unresolved import `E`
109
}
1110

1211
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
error: imports can only refer to extern crate names passed with `--extern` in macros originating from 2015 edition
2-
--> <::edition_imports_2015::gen_gated macros>:1:50
1+
error[E0432]: unresolved import `E`
2+
--> $DIR/edition-imports-virtual-2015-gated.rs:8:5
33
|
4-
LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
5-
| ^
6-
|
7-
::: $DIR/edition-imports-virtual-2015-gated.rs:9:5
4+
LL | gen_gated!(); //~ ERROR unresolved import `E`
5+
| ^^^^^^^^^^^^^ could not find `E` in `{{root}}`
86
|
9-
LL | gen_gated!();
10-
| ------------- not an extern crate passed with `--extern`
11-
|
12-
note: this import refers to the enum defined here
13-
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
14-
|
15-
LL | gen_gated!();
16-
| ^^^^^^^^^^^^^
177
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
188

199
error: aborting due to previous error
2010

11+
For more information about this error, try `rustc --explain E0432`.

src/test/ui/error-codes/E0432.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0432]: unresolved import `something`
22
--> $DIR/E0432.rs:1:5
33
|
44
LL | use something::Foo; //~ ERROR E0432
5-
| ^^^^^^^^^ maybe a missing `extern crate something;`?
5+
| ^^^^^^^^^ could not find `something` in `{{root}}`
66

77
error: aborting due to previous error
88

src/test/ui/extenv/issue-55897.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ error[E0432]: unresolved import `prelude`
88
--> $DIR/issue-55897.rs:1:5
99
|
1010
LL | use prelude::*; //~ ERROR unresolved import `prelude`
11-
| ^^^^^^^ did you mean `std::prelude`?
11+
| ^^^^^^^ could not find `prelude` in `{{root}}`
1212

1313
error: cannot determine resolution for the macro `env`
1414
--> $DIR/issue-55897.rs:6:22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use core::default; //~ ERROR unresolved import `core`
1+
use core::default;
22

33
fn main() {
4-
let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
4+
let _: u8 = ::core::default::Default();
5+
//~^ ERROR expected function, found trait `core::default::Default`
56
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
error[E0432]: unresolved import `core`
2-
--> $DIR/feature-gate-extern_absolute_paths.rs:1:5
1+
error[E0423]: expected function, found trait `core::default::Default`
2+
--> $DIR/feature-gate-extern_absolute_paths.rs:4:17
33
|
4-
LL | use core::default; //~ ERROR unresolved import `core`
5-
| ^^^^ maybe a missing `extern crate core;`?
4+
LL | let _: u8 = ::core::default::Default();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ not a function
66

7-
error[E0433]: failed to resolve: maybe a missing `extern crate core;`?
8-
--> $DIR/feature-gate-extern_absolute_paths.rs:4:19
9-
|
10-
LL | let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
11-
| ^^^^ maybe a missing `extern crate core;`?
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

15-
Some errors occurred: E0432, E0433.
16-
For more information about an error, try `rustc --explain E0432`.
9+
For more information about this error, try `rustc --explain E0423`.

src/test/ui/hidden-rt-injection.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0432]: unresolved import `native`
22
--> $DIR/hidden-rt-injection.rs:5:9
33
|
44
LL | use native; //~ ERROR unresolved import
5-
| ^^^^^^ no `native` in the root
5+
| ^^^^^^ no `native` external crate
66

77
error: aborting due to previous error
88

src/test/ui/hidden-rt-injection2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0432]: unresolved import `rt`
22
--> $DIR/hidden-rt-injection2.rs:5:9
33
|
44
LL | use rt; //~ ERROR unresolved import
5-
| ^^ no `rt` in the root
5+
| ^^ no `rt` external crate
66

77
error: aborting due to previous error
88

src/test/ui/import.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
66
mod zed {
77
pub fn bar() { println!("bar"); }
88
use foo; //~ ERROR unresolved import `foo` [E0432]
9-
//~^ no `foo` in the root
109
}
1110

1211
fn main() {

src/test/ui/import.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ error[E0432]: unresolved import `foo`
88
--> $DIR/import.rs:8:9
99
|
1010
LL | use foo; //~ ERROR unresolved import `foo` [E0432]
11-
| ^^^ no `foo` in the root
11+
| ^^^ no `foo` external crate
1212

1313
error[E0603]: unresolved item `foo` is private
14-
--> $DIR/import.rs:13:10
14+
--> $DIR/import.rs:12:10
1515
|
1616
LL | zed::foo(); //~ ERROR `foo` is private
1717
| ^^^

0 commit comments

Comments
 (0)