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 {
base.into_iter().collect(),
subclass.clone(),
source.span,
- id,
+ canary_id,
root_use_tree.span,
root_id,
ty::Visibility::Invisible,
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);
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();
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+use std;
+
+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();
+}
+++ /dev/null
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// edition:2018
-
-#![feature(uniform_paths)]
-
-use std;
-
-fn main() {}
+++ /dev/null
-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
-