diff options
| author | bors <bors@rust-lang.org> | 2018-09-06 23:29:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-09-06 23:29:56 +0000 |
| commit | ad7b22ef29eb7e6a2ca8395b595afaf6ec26efee (patch) | |
| tree | e1a70231d7cd80059df4a641c959269e0cab0693 /src | |
| parent | a8c11d216b04abe21a03220b344f1415e1d6ebd1 (diff) | |
| parent | 31fce914b27497addbbc9f8235fdecc0962f2f98 (diff) | |
| download | rust-ad7b22ef29eb7e6a2ca8395b595afaf6ec26efee.tar.gz rust-ad7b22ef29eb7e6a2ca8395b595afaf6ec26efee.zip | |
Auto merge of #54005 - eddyb:uniform-paths-self-resolve, r=petrochenkov
rustc_resolve: allow `use crate_name;` under `uniform_paths`.
Specifically, `use crate_name;` and `use crate_name::{self, ...};` are now allowed, whereas previously there would produce a (false positive) ambiguity error, as the ambiguity detection code was seeing the `crate_name` import as a locally-available definition to conflict with the crate.
r? @petrochenkov cc @aturon @joshtriplett @Centril
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 19 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 24 | ||||
| -rw-r--r-- | src/test/run-pass/redundant.rs (renamed from src/test/ui/rust-2018/uniform-paths/redundant.rs) | 14 | ||||
| -rw-r--r-- | src/test/ui/rust-2018/uniform-paths/redundant.stderr | 14 |
4 files changed, 39 insertions, 32 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 80f6c263e19..37868a83e34 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -181,6 +181,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.session.features_untracked().uniform_paths); let source = module_path[0]; + + // HACK(eddyb) For `use x::{self, ...};`, use the ID of the + // `self` nested import for the canary. This allows the + // ambiguity reporting scope to ignore false positives + // in the same way it does for `use x;` (by comparing IDs). + let mut canary_id = id; + if let ast::UseTreeKind::Nested(ref items) = use_tree.kind { + for &(ref use_tree, id) in items { + if let ast::UseTreeKind::Simple(..) = use_tree.kind { + if use_tree.ident().name == keywords::SelfValue.name() { + canary_id = id; + break; + } + } + } + } + // Helper closure to emit a canary with the given base path. let emit = |this: &mut Self, base: Option<Ident>| { let subclass = SingleImport { @@ -200,7 +217,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { base.into_iter().collect(), subclass.clone(), source.span, - id, + canary_id, root_use_tree.span, root_id, ty::Visibility::Invisible, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c60f9293d58..73c9af0d11c 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -664,6 +664,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { self.per_ns(|_, ns| { if let Some(result) = result[ns].get().ok() { + if let NameBindingKind::Import { directive, .. } = result.kind { + // Skip canaries that resolve to the import itself. + // These come from `use crate_name;`, which isn't really + // ambiguous, as the import can't actually shadow itself. + if directive.id == import.id { + return; + } + } if has_explicit_self { // There should only be one `self::x` (module-scoped) canary. assert_eq!(canary_results[ns].module_scope, None); @@ -718,22 +726,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { errors = true; - // Special-case the error when `self::x` finds its own `use x;`. - if has_external_crate && - results.module_scope == Some(span) && - results.block_scopes.is_empty() { - let msg = format!("`{}` import is redundant", name); - this.session.struct_span_err(span, &msg) - .span_label(span, - format!("refers to external crate `::{}`", name)) - .span_label(span, - format!("defines `self::{}`, shadowing itself", name)) - .help(&format!("remove or write `::{}` explicitly instead", name)) - .note("relative `use` paths enabled by `#![feature(uniform_paths)]`") - .emit(); - return; - } - let msg = format!("`{}` import is ambiguous", name); let mut err = this.session.struct_span_err(span, &msg); let mut suggestion_choices = String::new(); diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.rs b/src/test/run-pass/redundant.rs index 8f384b7e7af..39bd3160695 100644 --- a/src/test/ui/rust-2018/uniform-paths/redundant.rs +++ b/src/test/run-pass/redundant.rs @@ -14,4 +14,16 @@ use std; -fn main() {} +mod foo { + pub use std as my_std; +} + +mod bar { + pub use std::{self}; +} + +fn main() { + self::std::io::stdout(); + foo::my_std::io::stdout(); + bar::std::io::stdout(); +} diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.stderr b/src/test/ui/rust-2018/uniform-paths/redundant.stderr deleted file mode 100644 index dd38407e164..00000000000 --- a/src/test/ui/rust-2018/uniform-paths/redundant.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `std` import is redundant - --> $DIR/redundant.rs:15:5 - | -LL | use std; - | ^^^ - | | - | refers to external crate `::std` - | defines `self::std`, shadowing itself - | - = help: remove or write `::std` explicitly instead - = note: relative `use` paths enabled by `#![feature(uniform_paths)]` - -error: aborting due to previous error - |
