resolve: Reintroduce feature gate for uniform paths in imports

This commit is contained in:
Vadim Petrochenkov 2018-11-12 03:58:39 +03:00
parent a38f903114
commit 8e88c3470a
30 changed files with 168 additions and 80 deletions

View File

@ -11,8 +11,8 @@ introducing `extern crate` items, using keyword `extern`.
For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
`feature(extern_absolute_paths)` mode provides the same effect by resolving absolute paths like
`::my_crate::a::b` to paths from extern crates by default.
Absolute paths on 2018 edition (e.g. `::my_crate::a::b`) provide the same effect
and resolve to extern crates (built-in or passed with `--extern`).
```rust,ignore
#![feature(extern_in_paths)]

View File

@ -4736,6 +4736,34 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
}
fn binding_description(&self, b: &NameBinding, ident: Ident, from_prelude: bool) -> String {
if b.span.is_dummy() {
let add_built_in = match b.def() {
// These already contain the "built-in" prefix or look bad with it.
Def::NonMacroAttr(..) | Def::PrimTy(..) | Def::ToolMod => false,
_ => true,
};
let (built_in, from) = if from_prelude {
("", " from prelude")
} else if b.is_extern_crate() && !b.is_import() &&
self.session.opts.externs.get(&ident.as_str()).is_some() {
("", " passed with `--extern`")
} else if add_built_in {
(" built-in", "")
} else {
("", "")
};
let article = if built_in.is_empty() { b.article() } else { "a" };
format!("{a}{built_in} {thing}{from}",
a = article, thing = b.descr(), built_in = built_in, from = from)
} else {
let introduced = if b.is_import() { "imported" } else { "defined" };
format!("the {thing} {introduced} here",
thing = b.descr(), introduced = introduced)
}
}
fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError) {
let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
@ -4751,31 +4779,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
err.span_label(ident.span, "ambiguous name");
let mut could_refer_to = |b: &NameBinding, misc: AmbiguityErrorMisc, also: &str| {
let what = if b.span.is_dummy() {
let add_built_in = match b.def() {
// These already contain the "built-in" prefix or look bad with it.
Def::NonMacroAttr(..) | Def::PrimTy(..) | Def::ToolMod => false,
_ => true,
};
let (built_in, from) = if misc == AmbiguityErrorMisc::FromPrelude {
("", " from prelude")
} else if b.is_extern_crate() && !b.is_import() &&
self.session.opts.externs.get(&ident.as_str()).is_some() {
("", " passed with `--extern`")
} else if add_built_in {
(" built-in", "")
} else {
("", "")
};
let article = if built_in.is_empty() { b.article() } else { "a" };
format!("{a}{built_in} {thing}{from}",
a = article, thing = b.descr(), built_in = built_in, from = from)
} else {
let participle = if b.is_import() { "imported" } else { "defined" };
format!("the {thing} {introduced} here",
thing = b.descr(), introduced = participle)
};
let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
let note_msg = format!("`{ident}` could{also} refer to {what}",
ident = ident, also = also, what = what);

View File

@ -891,7 +891,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
// The first found solution was the only one, return it.
if let Some((binding, ..)) = 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
// 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.
if ns != TypeNS || !use_prelude ||
self.extern_prelude_get(ident, true, false).is_none() {
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(&note_msg);
} else {
err.span_note(binding.span, &note_msg);
err.span_label(binding.span, "not an extern crate passed with `--extern`");
}
err.emit();
}
}
return Ok(binding);
}

View File

@ -8,15 +8,22 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// edition:2018
pub mod foo {
pub use bar::Bar;
//~^ ERROR unresolved import `bar`
pub use bar::Bar; //~ ERROR imports can only refer to extern crate names
pub mod bar {
pub struct Bar;
}
}
use inline; //~ ERROR imports can only refer to extern crate names
use Vec; //~ ERROR imports can only refer to extern crate names
use vec; //~ ERROR imports can only refer to extern crate names
fn main() {
let _ = foo::Bar;
}

View File

@ -1,9 +1,62 @@
error[E0432]: unresolved import `bar`
--> $DIR/feature-gate-uniform-paths.rs:12:13
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
--> $DIR/feature-gate-uniform-paths.rs:14:13
|
LL | pub use bar::Bar;
| ^^^ Did you mean `self::bar`?
LL | pub use bar::Bar; //~ ERROR imports can only refer to extern crate names
| ^^^
LL |
LL | / pub mod bar {
LL | | pub struct Bar;
LL | | }
| |_____- not an extern crate passed with `--extern`
|
= help: add #![feature(uniform_paths)] to the crate attributes to enable
note: this import refers to the module defined here
--> $DIR/feature-gate-uniform-paths.rs:16:5
|
LL | / pub mod bar {
LL | | pub struct Bar;
LL | | }
| |_____^
error: aborting due to previous error
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
--> $DIR/feature-gate-uniform-paths.rs:21:5
|
LL | use inline; //~ ERROR imports can only refer to extern crate names
| ^^^^^^ not an extern crate passed with `--extern`
|
= help: add #![feature(uniform_paths)] to the crate attributes to enable
note: this import refers to the built-in attribute imported here
--> $DIR/feature-gate-uniform-paths.rs:21:5
|
LL | use inline; //~ ERROR imports can only refer to extern crate names
| ^^^^^^
For more information about this error, try `rustc --explain E0432`.
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
--> $DIR/feature-gate-uniform-paths.rs:23:5
|
LL | use Vec; //~ ERROR imports can only refer to extern crate names
| ^^^ not an extern crate passed with `--extern`
|
= help: add #![feature(uniform_paths)] to the crate attributes to enable
note: this import refers to the struct imported here
--> $DIR/feature-gate-uniform-paths.rs:23:5
|
LL | use Vec; //~ ERROR imports can only refer to extern crate names
| ^^^
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
--> $DIR/feature-gate-uniform-paths.rs:25:5
|
LL | use vec; //~ ERROR imports can only refer to extern crate names
| ^^^ not an extern crate passed with `--extern`
|
= help: add #![feature(uniform_paths)] to the crate attributes to enable
note: this import refers to the macro imported here
--> $DIR/feature-gate-uniform-paths.rs:25:5
|
LL | use vec; //~ ERROR imports can only refer to extern crate names
| ^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -10,6 +10,8 @@
// edition:2018
#![feature(uniform_paths)]
// Tests that arbitrary crates (other than `core`, `std` and `meta`)
// aren't allowed without `--extern`, even if they're in the sysroot.
use alloc; //~ ERROR unresolved import `alloc`

View File

@ -1,11 +1,11 @@
error: cannot import a built-in macro
--> $DIR/not-whitelisted.rs:16:5
--> $DIR/not-whitelisted.rs:18:5
|
LL | use test; //~ ERROR cannot import a built-in macro
| ^^^^
error[E0432]: unresolved import `alloc`
--> $DIR/not-whitelisted.rs:15:5
--> $DIR/not-whitelisted.rs:17:5
|
LL | use alloc; //~ ERROR unresolved import `alloc`
| ^^^^^ no `alloc` external crate

View File

@ -12,6 +12,8 @@
// compile-flags:--extern baz
// edition:2018
#![feature(uniform_paths)]
mod foo {
pub type Bar = u32;
}

View File

@ -1,5 +1,5 @@
error[E0432]: unresolved import `foo`
--> $DIR/local-path-suggestions-2018.rs:20:9
--> $DIR/local-path-suggestions-2018.rs:22:9
|
LL | use foo::Bar;
| ^^^ Did you mean `crate::foo`?
@ -7,7 +7,7 @@ LL | use foo::Bar;
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
error[E0432]: unresolved import `foobar`
--> $DIR/local-path-suggestions-2018.rs:29:5
--> $DIR/local-path-suggestions-2018.rs:31:5
|
LL | use foobar::Baz;
| ^^^^^^ Did you mean `baz::foobar`?

View File

@ -10,7 +10,7 @@
// edition:2018
// Dummy import to introduce `uniform_paths` canaries.
// Dummy import that previously introduced uniform path canaries.
use std;
// fn version() -> &'static str {""}

View File

@ -10,8 +10,6 @@
// edition:2018
#![feature(uniform_paths)]
// This test is similar to `ambiguity-macros.rs`, but nested in a module.
mod foo {

View File

@ -1,5 +1,5 @@
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/ambiguity-macros-nested.rs:18:13
--> $DIR/ambiguity-macros-nested.rs:16:13
|
LL | pub use std::io;
| ^^^ ambiguous name
@ -7,7 +7,7 @@ LL | pub use std::io;
= note: `std` could refer to a built-in extern crate
= help: use `::std` to refer to this extern crate unambiguously
note: `std` could also refer to the module defined here
--> $DIR/ambiguity-macros-nested.rs:23:13
--> $DIR/ambiguity-macros-nested.rs:21:13
|
LL | / mod std {
LL | | pub struct io;

View File

@ -10,8 +10,6 @@
// edition:2018
#![feature(uniform_paths)]
// This test is similar to `ambiguity.rs`, but with macros defining local items.
use std::io;

View File

@ -1,5 +1,5 @@
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/ambiguity-macros.rs:17:5
--> $DIR/ambiguity-macros.rs:15:5
|
LL | use std::io;
| ^^^ ambiguous name
@ -7,7 +7,7 @@ LL | use std::io;
= note: `std` could refer to a built-in extern crate
= help: use `::std` to refer to this extern crate unambiguously
note: `std` could also refer to the module defined here
--> $DIR/ambiguity-macros.rs:22:9
--> $DIR/ambiguity-macros.rs:20:9
|
LL | / mod std {
LL | | pub struct io;

View File

@ -10,8 +10,6 @@
// edition:2018
#![feature(uniform_paths)]
// This test is similar to `ambiguity.rs`, but nested in a module.
mod foo {

View File

@ -1,5 +1,5 @@
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/ambiguity-nested.rs:18:13
--> $DIR/ambiguity-nested.rs:16:13
|
LL | pub use std::io;
| ^^^ ambiguous name
@ -7,7 +7,7 @@ LL | pub use std::io;
= note: `std` could refer to a built-in extern crate
= help: use `::std` to refer to this extern crate unambiguously
note: `std` could also refer to the module defined here
--> $DIR/ambiguity-nested.rs:21:5
--> $DIR/ambiguity-nested.rs:19:5
|
LL | / mod std {
LL | | pub struct io;

View File

@ -10,8 +10,6 @@
// edition:2018
#![feature(uniform_paths)]
use std::io;
//~^ ERROR `std` is ambiguous

View File

@ -1,5 +1,5 @@
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/ambiguity.rs:15:5
--> $DIR/ambiguity.rs:13:5
|
LL | use std::io;
| ^^^ ambiguous name
@ -7,7 +7,7 @@ LL | use std::io;
= note: `std` could refer to a built-in extern crate
= help: use `::std` to refer to this extern crate unambiguously
note: `std` could also refer to the module defined here
--> $DIR/ambiguity.rs:18:1
--> $DIR/ambiguity.rs:16:1
|
LL | / mod std {
LL | | pub struct io;

View File

@ -1,5 +1,7 @@
// edition:2018
#![feature(uniform_paths)]
mod my {
pub mod sub {
pub fn bar() {}

View File

@ -1,16 +1,16 @@
error[E0659]: `sub` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow-nested.rs:16:13
--> $DIR/block-scoped-shadow-nested.rs:18:13
|
LL | use sub::bar; //~ ERROR `sub` is ambiguous
| ^^^ ambiguous name
|
note: `sub` could refer to the module imported here
--> $DIR/block-scoped-shadow-nested.rs:14:9
--> $DIR/block-scoped-shadow-nested.rs:16:9
|
LL | use my::sub;
| ^^^^^^^
note: `sub` could also refer to the module defined here
--> $DIR/block-scoped-shadow-nested.rs:9:1
--> $DIR/block-scoped-shadow-nested.rs:11:1
|
LL | / mod sub {
LL | | pub fn bar() {}

View File

@ -10,8 +10,6 @@
// edition:2018
#![feature(uniform_paths)]
enum Foo {}
struct std;

View File

@ -1,52 +1,52 @@
error[E0659]: `Foo` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:21:9
--> $DIR/block-scoped-shadow.rs:19:9
|
LL | use Foo::*;
| ^^^ ambiguous name
|
note: `Foo` could refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:20:5
--> $DIR/block-scoped-shadow.rs:18:5
|
LL | enum Foo { A, B }
| ^^^^^^^^^^^^^^^^^
note: `Foo` could also refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:15:1
--> $DIR/block-scoped-shadow.rs:13:1
|
LL | enum Foo {}
| ^^^^^^^^^^^
= help: use `self::Foo` to refer to this enum unambiguously
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:28:9
--> $DIR/block-scoped-shadow.rs:26:9
|
LL | use std as foo;
| ^^^ ambiguous name
|
note: `std` could refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:27:5
--> $DIR/block-scoped-shadow.rs:25:5
|
LL | enum std {}
| ^^^^^^^^^^^
note: `std` could also refer to the struct defined here
--> $DIR/block-scoped-shadow.rs:17:1
--> $DIR/block-scoped-shadow.rs:15:1
|
LL | struct std;
| ^^^^^^^^^^^
= help: use `self::std` to refer to this struct unambiguously
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:28:9
--> $DIR/block-scoped-shadow.rs:26:9
|
LL | use std as foo;
| ^^^ ambiguous name
|
note: `std` could refer to the function defined here
--> $DIR/block-scoped-shadow.rs:26:5
--> $DIR/block-scoped-shadow.rs:24:5
|
LL | fn std() {}
| ^^^^^^^^^^^
note: `std` could also refer to the unit struct defined here
--> $DIR/block-scoped-shadow.rs:17:1
--> $DIR/block-scoped-shadow.rs:15:1
|
LL | struct std;
| ^^^^^^^^^^^

View File

@ -1,6 +1,8 @@
// compile-pass
// edition:2018
#![feature(uniform_paths)]
fn main() {
enum E { A, B, C }

View File

@ -10,9 +10,7 @@
// edition:2018
#![feature(uniform_paths)]
// Dummy import to introduce `uniform_paths` canaries.
// Dummy import that previously introduced uniform path canaries.
use std;
// fn version() -> &'static str {""}

View File

@ -1,5 +1,5 @@
error[E0432]: unresolved import `crate::version`
--> $DIR/issue-54253.rs:22:9
--> $DIR/issue-54253.rs:20:9
|
LL | use crate::version; //~ ERROR unresolved import `crate::version`
| ^^^^^^^^^^^^^^ no `version` in the root

View File

@ -2,7 +2,7 @@
// For the time being `macro_rules` items are treated as *very* private...
#![feature(underscore_imports, decl_macro)]
#![feature(underscore_imports, decl_macro, uniform_paths)]
mod m1 {
macro_rules! legacy_macro { () => () }

View File

@ -1,5 +1,7 @@
// edition:2018
#![feature(uniform_paths)]
// Built-in macro
use env as env_imported; //~ ERROR cannot import a built-in macro

View File

@ -1,11 +1,11 @@
error: cannot import a built-in macro
--> $DIR/prelude-fail.rs:4:5
--> $DIR/prelude-fail.rs:6:5
|
LL | use env as env_imported; //~ ERROR cannot import a built-in macro
| ^^^^^^^^^^^^^^^^^^^
error[E0432]: unresolved import `rustfmt`
--> $DIR/prelude-fail.rs:7:5
--> $DIR/prelude-fail.rs:9:5
|
LL | use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
| ^^^^^^^ Not a module `rustfmt`

View File

@ -1,6 +1,8 @@
// compile-pass
// edition:2018
#![feature(uniform_paths)]
// Macro imported with `#[macro_use] extern crate`
use vec as imported_vec;

View File

@ -11,8 +11,6 @@
// run-pass
// edition:2018
#![feature(uniform_paths)]
use std;
use std::io;