about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-09-06 23:29:56 +0000
committerbors <bors@rust-lang.org>2018-09-06 23:29:56 +0000
commitad7b22ef29eb7e6a2ca8395b595afaf6ec26efee (patch)
treee1a70231d7cd80059df4a641c959269e0cab0693 /src
parenta8c11d216b04abe21a03220b344f1415e1d6ebd1 (diff)
parent31fce914b27497addbbc9f8235fdecc0962f2f98 (diff)
downloadrust-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.rs19
-rw-r--r--src/librustc_resolve/resolve_imports.rs24
-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.stderr14
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
-