提交 8bf1f1c8 编写于 作者: B bors

Auto merge of #58349 - petrochenkov:uni201x, r=pnkfelix

resolve: Simplify import resolution for mixed 2015/2018 edition mode

Non-controversial part of https://github.com/rust-lang/rust/pull/57745.

Before:

| Local edition (per-span) | Global edition (--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 (future-proofed to error if the result is not Crate-relative or from Extern prelude) | Crate-relative with fallback to Extern prelude |

After:

| Local edition (per-span) | Global edition (--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 Extern prelude | Crate-relative with fallback to Extern prelude |

I.e. only the behavior of the mixed local-2015-global-2018 mode is changed.
This mixed mode has two goals:
- Address regressions from https://github.com/rust-lang/rust/pull/56053#issuecomment-440826397.
Both "before" and "after" variants address those regressions.
- Be retrofit-able to "full 2015" edition (https://github.com/rust-lang/rust/pull/57745).
Any more complex fallback scheme (with more candidates) than "Crate-relative with fallback to Extern prelude" will give more regressions than https://github.com/rust-lang/rust/pull/57745#issuecomment-455855089 and is therefore less retrofit-able while also being, well, more complex.
So, we can settle on "Crate-relative with fallback to Extern prelude".

(I'll hopefully proceed with https://github.com/rust-lang/rust/pull/57745 after mid-February.)

r? @Centril
......@@ -131,12 +131,9 @@ fn build_reduced_graph_for_use_tree(
// so prefixes are prepended with crate root segment if necessary.
// The root is prepended lazily, when the first non-empty prefix or terminating glob
// appears, so imports in braced groups can have roots prepended independently.
// 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't
// get crate root prepended, but get special treatment during in-scope resolution instead.
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
let crate_root = match prefix_iter.peek() {
Some(seg) if !seg.ident.is_path_segment_keyword() &&
seg.ident.span.rust_2015() && self.session.rust_2015() => {
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
Some(seg.ident.span.ctxt())
}
None if is_glob && use_tree.span.rust_2015() => {
......
......@@ -1273,7 +1273,6 @@ struct UseError<'a> {
#[derive(Clone, Copy, PartialEq, Debug)]
enum AmbiguityKind {
Import,
AbsolutePath,
BuiltinAttr,
DeriveHelper,
LegacyHelperVsPrelude,
......@@ -1289,8 +1288,6 @@ fn descr(self) -> &'static str {
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 =>
......
......@@ -572,7 +572,7 @@ struct Flags: u8 {
ScopeSet::Module => (TypeNS, None, false, false),
};
let mut where_to_resolve = match ns {
_ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot,
_ if is_absolute_path => WhereToResolve::CrateRoot,
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
MacroNS => WhereToResolve::DeriveHelpers,
};
......@@ -770,8 +770,6 @@ struct Flags: u8 {
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 {
......@@ -841,18 +839,13 @@ struct Flags: u8 {
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
LegacyScope::Uninitialized => unreachable!(),
}
WhereToResolve::CrateRoot if is_import => match ns {
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
MacroNS => WhereToResolve::DeriveHelpers,
}
WhereToResolve::CrateRoot if is_absolute_path => match ns {
WhereToResolve::CrateRoot => 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),
......@@ -885,44 +878,7 @@ struct Flags: u8 {
}
// The first found solution was the only one, return it.
if let Some((binding, flags)) = innermost_result {
// We get to here only if there's no ambiguity, in ambiguous cases an error will
// be reported anyway, so there's no reason to report an additional feature error.
// The `binding` can actually be introduced by something other than `--extern`,
// but its `Def` should coincide with a crate passed with `--extern`
// (otherwise there would be ambiguity) and we can skip feature error in this case.
'ok: {
if !is_import || !rust_2015 {
break 'ok;
}
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
break 'ok;
}
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
let root_module = self.resolve_crate_root(root_ident);
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
orig_ident, ns, None, false, path_span)
.is_ok() {
break 'ok;
}
let msg = "imports can only refer to extern crate names passed with \
`--extern` in macros originating from 2015 edition";
let mut err = self.session.struct_span_err(ident.span, msg);
let what = self.binding_description(binding, ident,
flags.contains(Flags::MISC_FROM_PRELUDE));
let note_msg = format!("this import refers to {what}", what = what);
let label_span = if binding.span.is_dummy() {
err.note(&note_msg);
ident.span
} else {
err.span_note(binding.span, &note_msg);
binding.span
};
err.span_label(label_span, "not an extern crate passed with `--extern`");
err.emit();
}
if let Some((binding, _)) = innermost_result {
return Ok(binding);
}
......
// compile-pass
// edition:2018
// compile-flags:--extern edition_imports_2015
// aux-build:edition-imports-2015.rs
......@@ -12,8 +13,7 @@ mod check {
pub struct Ambiguous {}
fn check() {
edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
//~| ERROR `edition_imports_2015` is ambiguous
edition_imports_2015::gen_ambiguous!(); // OK
}
}
......
error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution)
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9
|
LL | edition_imports_2015::gen_ambiguous!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
|
note: `Ambiguous` could refer to the struct defined here
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:9:1
|
LL | pub struct Ambiguous {}
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: use `crate::Ambiguous` to refer to this struct unambiguously
note: `Ambiguous` could also refer to the struct defined here
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:12:5
|
LL | pub struct Ambiguous {}
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: use `self::Ambiguous` to refer to this struct unambiguously
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution)
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9
|
LL | edition_imports_2015::gen_ambiguous!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
|
= note: `edition_imports_2015` could refer to an extern crate passed with `--extern`
note: `edition_imports_2015` could also refer to the module defined here
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:5:1
|
LL | / mod edition_imports_2015 {
LL | | pub struct Path;
LL | | }
| |_^
= help: use `crate::edition_imports_2015` to refer to this module unambiguously
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0659`.
// edition:2018
// aux-build:edition-imports-2015.rs
// error-pattern: imports can only refer to extern crate names passed with `--extern`
#[macro_use]
extern crate edition_imports_2015;
mod check {
gen_gated!();
gen_gated!(); //~ ERROR unresolved import `E`
}
fn main() {}
error: imports can only refer to extern crate names passed with `--extern` in macros originating from 2015 edition
--> <::edition_imports_2015::gen_gated macros>:1:50
|
LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
| ^
|
::: $DIR/edition-imports-virtual-2015-gated.rs:9:5
error[E0432]: unresolved import `E`
--> $DIR/edition-imports-virtual-2015-gated.rs:8:5
|
LL | gen_gated!();
| ------------- not an extern crate passed with `--extern`
|
note: this import refers to the enum defined here
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
| ^^^^^^^^^^^^^ could not find `E` in `{{root}}`
|
LL | gen_gated!();
| ^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册