resolve: Fallback to uniform paths in 2015 imports used from global 2018 edition
This commit is contained in:
parent
dae4c7b1ff
commit
c06e69ee70
9 changed files with 187 additions and 38 deletions
|
@ -132,9 +132,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
// so prefixes are prepended with crate root segment if necessary.
|
// so prefixes are prepended with crate root segment if necessary.
|
||||||
// The root is prepended lazily, when the first non-empty prefix or terminating glob
|
// 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.
|
// 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 is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
|
||||||
let crate_root = match prefix_iter.peek() {
|
let crate_root = match prefix_iter.peek() {
|
||||||
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
|
Some(seg) if !seg.ident.is_path_segment_keyword() &&
|
||||||
|
seg.ident.span.rust_2015() && self.session.rust_2015() => {
|
||||||
Some(seg.ident.span.ctxt())
|
Some(seg.ident.span.ctxt())
|
||||||
}
|
}
|
||||||
None if is_glob && use_tree.span.rust_2015() => {
|
None if is_glob && use_tree.span.rust_2015() => {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
|
#![feature(label_break_value)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
#![feature(slice_sort_by_cached_key)]
|
#![feature(slice_sort_by_cached_key)]
|
||||||
|
@ -2191,28 +2192,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
fn resolve_ident_in_module(
|
fn resolve_ident_in_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
module: ModuleOrUniformRoot<'a>,
|
module: ModuleOrUniformRoot<'a>,
|
||||||
mut ident: Ident,
|
ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
parent_scope: Option<&ParentScope<'a>>,
|
parent_scope: Option<&ParentScope<'a>>,
|
||||||
record_used: bool,
|
record_used: bool,
|
||||||
path_span: Span
|
path_span: Span
|
||||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||||
ident.span = ident.span.modern();
|
self.resolve_ident_in_module_ext(
|
||||||
|
module, ident, ns, parent_scope, record_used, path_span
|
||||||
|
).map_err(|(determinacy, _)| determinacy)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_ident_in_module_ext(
|
||||||
|
&mut self,
|
||||||
|
module: ModuleOrUniformRoot<'a>,
|
||||||
|
mut ident: Ident,
|
||||||
|
ns: Namespace,
|
||||||
|
parent_scope: Option<&ParentScope<'a>>,
|
||||||
|
record_used: bool,
|
||||||
|
path_span: Span
|
||||||
|
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
|
||||||
let orig_current_module = self.current_module;
|
let orig_current_module = self.current_module;
|
||||||
match module {
|
match module {
|
||||||
ModuleOrUniformRoot::Module(module) => {
|
ModuleOrUniformRoot::Module(module) => {
|
||||||
|
ident.span = ident.span.modern();
|
||||||
if let Some(def) = ident.span.adjust(module.expansion) {
|
if let Some(def) = ident.span.adjust(module.expansion) {
|
||||||
self.current_module = self.macro_def_scope(def);
|
self.current_module = self.macro_def_scope(def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
|
ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
|
||||||
|
ident.span = ident.span.modern();
|
||||||
ident.span.adjust(Mark::root());
|
ident.span.adjust(Mark::root());
|
||||||
}
|
}
|
||||||
_ => {}
|
ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => {
|
||||||
|
// No adjustments
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let result = self.resolve_ident_in_module_unadjusted_ext(
|
let result = self.resolve_ident_in_module_unadjusted_ext(
|
||||||
module, ident, ns, parent_scope, false, record_used, path_span,
|
module, ident, ns, parent_scope, false, record_used, path_span,
|
||||||
).map_err(|(determinacy, _)| determinacy);
|
);
|
||||||
self.current_module = orig_current_module;
|
self.current_module = orig_current_module;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -526,7 +526,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
|
// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
|
||||||
crate fn early_resolve_ident_in_lexical_scope(
|
crate fn early_resolve_ident_in_lexical_scope(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut ident: Ident,
|
orig_ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
macro_kind: Option<MacroKind>,
|
macro_kind: Option<MacroKind>,
|
||||||
is_import: bool,
|
is_import: bool,
|
||||||
|
@ -582,6 +582,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
enum WhereToResolve<'a> {
|
enum WhereToResolve<'a> {
|
||||||
DeriveHelpers,
|
DeriveHelpers,
|
||||||
MacroRules(LegacyScope<'a>),
|
MacroRules(LegacyScope<'a>),
|
||||||
|
CrateRoot,
|
||||||
Module(Module<'a>),
|
Module(Module<'a>),
|
||||||
MacroUsePrelude,
|
MacroUsePrelude,
|
||||||
BuiltinMacros,
|
BuiltinMacros,
|
||||||
|
@ -605,8 +606,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
|
|
||||||
assert!(force || !record_used); // `record_used` implies `force`
|
assert!(force || !record_used); // `record_used` implies `force`
|
||||||
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
|
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
|
||||||
let rust_2015 = ident.span.rust_2015();
|
let rust_2015 = orig_ident.span.rust_2015();
|
||||||
ident = ident.modern();
|
let mut ident = orig_ident.modern();
|
||||||
|
|
||||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||||
if ident.is_path_segment_keyword() {
|
if ident.is_path_segment_keyword() {
|
||||||
|
@ -627,10 +628,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
|
let mut innermost_result: Option<(&NameBinding, Flags)> = None;
|
||||||
|
|
||||||
// Go through all the scopes and try to resolve the name.
|
// Go through all the scopes and try to resolve the name.
|
||||||
let mut where_to_resolve = if ns == MacroNS {
|
let mut where_to_resolve = match ns {
|
||||||
WhereToResolve::DeriveHelpers
|
_ if is_import && rust_2015 => WhereToResolve::CrateRoot,
|
||||||
} else {
|
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
|
||||||
WhereToResolve::Module(parent_scope.module)
|
MacroNS => WhereToResolve::DeriveHelpers,
|
||||||
};
|
};
|
||||||
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
let mut use_prelude = !parent_scope.module.no_implicit_prelude;
|
||||||
let mut determinacy = Determinacy::Determined;
|
let mut determinacy = Determinacy::Determined;
|
||||||
|
@ -668,6 +669,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
Err(Determinacy::Undetermined),
|
Err(Determinacy::Undetermined),
|
||||||
_ => Err(Determinacy::Determined),
|
_ => Err(Determinacy::Determined),
|
||||||
}
|
}
|
||||||
|
WhereToResolve::CrateRoot => {
|
||||||
|
let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
|
||||||
|
let root_module = self.resolve_crate_root(root_ident);
|
||||||
|
let binding = self.resolve_ident_in_module_ext(
|
||||||
|
ModuleOrUniformRoot::Module(root_module),
|
||||||
|
orig_ident,
|
||||||
|
ns,
|
||||||
|
None,
|
||||||
|
record_used,
|
||||||
|
path_span,
|
||||||
|
);
|
||||||
|
match binding {
|
||||||
|
Ok(binding) => Ok((binding, Flags::MODULE)),
|
||||||
|
Err((Determinacy::Undetermined, Weak::No)) =>
|
||||||
|
return Err(Determinacy::determined(force)),
|
||||||
|
Err((Determinacy::Undetermined, Weak::Yes)) =>
|
||||||
|
Err(Determinacy::Undetermined),
|
||||||
|
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
|
||||||
|
}
|
||||||
|
}
|
||||||
WhereToResolve::Module(module) => {
|
WhereToResolve::Module(module) => {
|
||||||
let orig_current_module = mem::replace(&mut self.current_module, module);
|
let orig_current_module = mem::replace(&mut self.current_module, module);
|
||||||
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
let binding = self.resolve_ident_in_module_unadjusted_ext(
|
||||||
|
@ -816,7 +837,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
|
} else if innermost_flags.contains(Flags::MACRO_RULES) &&
|
||||||
flags.contains(Flags::MODULE) &&
|
flags.contains(Flags::MODULE) &&
|
||||||
!self.disambiguate_legacy_vs_modern(innermost_binding,
|
!self.disambiguate_legacy_vs_modern(innermost_binding,
|
||||||
binding) {
|
binding) ||
|
||||||
|
flags.contains(Flags::MACRO_RULES) &&
|
||||||
|
innermost_flags.contains(Flags::MODULE) &&
|
||||||
|
!self.disambiguate_legacy_vs_modern(binding,
|
||||||
|
innermost_binding) {
|
||||||
Some(AmbiguityKind::LegacyVsModern)
|
Some(AmbiguityKind::LegacyVsModern)
|
||||||
} else if innermost_binding.is_glob_import() {
|
} else if innermost_binding.is_glob_import() {
|
||||||
Some(AmbiguityKind::GlobVsOuter)
|
Some(AmbiguityKind::GlobVsOuter)
|
||||||
|
@ -867,6 +892,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
|
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
|
||||||
LegacyScope::Uninitialized => unreachable!(),
|
LegacyScope::Uninitialized => unreachable!(),
|
||||||
}
|
}
|
||||||
|
WhereToResolve::CrateRoot => match ns {
|
||||||
|
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
|
||||||
|
MacroNS => WhereToResolve::DeriveHelpers,
|
||||||
|
}
|
||||||
WhereToResolve::Module(module) => {
|
WhereToResolve::Module(module) => {
|
||||||
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
match self.hygienic_lexical_parent(module, &mut ident.span) {
|
||||||
Some(parent_module) => WhereToResolve::Module(parent_module),
|
Some(parent_module) => WhereToResolve::Module(parent_module),
|
||||||
|
@ -899,30 +928,43 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
|
|
||||||
// The first found solution was the only one, return it.
|
// The first found solution was the only one, return it.
|
||||||
if let Some((binding, flags)) = innermost_result {
|
if let Some((binding, flags)) = innermost_result {
|
||||||
if is_import && !self.session.features_untracked().uniform_paths {
|
// We get to here only if there's no ambiguity, in ambiguous cases an error will
|
||||||
// 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.
|
||||||
// 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`,
|
||||||
// The `binding` can actually be introduced by something other than `--extern`,
|
// but its `Def` should coincide with a crate passed with `--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.
|
||||||
// (otherwise there would be ambiguity) and we can skip feature error in this case.
|
'ok: {
|
||||||
if ns != TypeNS || !use_prelude ||
|
if !is_import || self.session.features_untracked().uniform_paths {
|
||||||
self.extern_prelude_get(ident, true).is_none() {
|
break 'ok;
|
||||||
let msg = "imports can only refer to extern crate names \
|
|
||||||
passed with `--extern` on stable channel";
|
|
||||||
let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
|
|
||||||
ident.span, GateIssue::Language, 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);
|
|
||||||
if binding.span.is_dummy() {
|
|
||||||
err.note(¬e_msg);
|
|
||||||
} else {
|
|
||||||
err.span_note(binding.span, ¬e_msg);
|
|
||||||
err.span_label(binding.span, "not an extern crate passed with `--extern`");
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
}
|
}
|
||||||
|
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
|
||||||
|
break 'ok;
|
||||||
|
}
|
||||||
|
if rust_2015 {
|
||||||
|
let root_ident = Ident::new(keywords::CrateRoot.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` on stable channel";
|
||||||
|
let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
|
||||||
|
ident.span, GateIssue::Language, 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);
|
||||||
|
if binding.span.is_dummy() {
|
||||||
|
err.note(¬e_msg);
|
||||||
|
} else {
|
||||||
|
err.span_note(binding.span, ¬e_msg);
|
||||||
|
err.span_label(binding.span, "not an extern crate passed with `--extern`");
|
||||||
|
}
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(binding);
|
return Ok(binding);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! gen_imports { () => {
|
macro_rules! gen_imports { () => {
|
||||||
use import::Path;
|
use import::Path;
|
||||||
// use std::collections::LinkedList; // FIXME
|
use std::collections::LinkedList;
|
||||||
|
|
||||||
fn check_absolute() {
|
fn check_absolute() {
|
||||||
::absolute::Path;
|
::absolute::Path;
|
||||||
|
@ -15,3 +15,16 @@ macro_rules! gen_imports { () => {
|
||||||
macro_rules! gen_glob { () => {
|
macro_rules! gen_glob { () => {
|
||||||
use *;
|
use *;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! gen_gated { () => {
|
||||||
|
fn check_gated() {
|
||||||
|
enum E { A }
|
||||||
|
use E::*;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! gen_ambiguous { () => {
|
||||||
|
use Ambiguous;
|
||||||
|
}}
|
||||||
|
|
|
@ -17,7 +17,7 @@ mod check {
|
||||||
|
|
||||||
fn check() {
|
fn check() {
|
||||||
Path;
|
Path;
|
||||||
// LinkedList::<u8>::new(); // FIXME
|
LinkedList::<u8>::new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// edition:2018
|
||||||
|
// aux-build:edition-imports-2015.rs
|
||||||
|
// error-pattern: `Ambiguous` is ambiguous
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate edition_imports_2015;
|
||||||
|
|
||||||
|
pub struct Ambiguous {}
|
||||||
|
|
||||||
|
mod check {
|
||||||
|
pub struct Ambiguous {}
|
||||||
|
|
||||||
|
fn check() {
|
||||||
|
gen_ambiguous!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution)
|
||||||
|
--> <::edition_imports_2015::gen_ambiguous macros>:1:15
|
||||||
|
|
|
||||||
|
LL | ( ) => { use Ambiguous ; }
|
||||||
|
| ^^^^^^^^^ ambiguous name
|
||||||
|
|
|
||||||
|
note: `Ambiguous` could refer to the struct defined here
|
||||||
|
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1
|
||||||
|
|
|
||||||
|
LL | pub struct Ambiguous {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: `Ambiguous` could also refer to the struct defined here
|
||||||
|
--> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5
|
||||||
|
|
|
||||||
|
LL | pub struct Ambiguous {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use `self::Ambiguous` to refer to this struct unambiguously
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0659`.
|
12
src/test/ui/editions/edition-imports-virtual-2015-gated.rs
Normal file
12
src/test/ui/editions/edition-imports-virtual-2015-gated.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// 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!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
|
||||||
|
--> <::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
|
||||||
|
|
|
||||||
|
LL | gen_gated!();
|
||||||
|
| ------------- not an extern crate passed with `--extern`
|
||||||
|
|
|
||||||
|
= help: add #![feature(uniform_paths)] to the crate attributes to enable
|
||||||
|
note: this import refers to the enum defined here
|
||||||
|
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
|
||||||
|
|
|
||||||
|
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 E0658`.
|
Loading…
Add table
Add a link
Reference in a new issue