From d0339c7e44ea145acdc779f0ecd078b11d212dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 7 Nov 2017 18:01:35 -0800 Subject: [PATCH] Fix help for duplicated names: `extern crate (...) as (...)` On the case of duplicated names caused by an `extern crate` statement with a rename, don't include the inline suggestion, instead using a span label with only the text to avoid incorrect rust code output. --- src/librustc_resolve/build_reduced_graph.rs | 4 ++-- src/librustc_resolve/check_unused.rs | 2 +- src/librustc_resolve/lib.rs | 14 ++++++++++++-- src/librustc_resolve/resolve_imports.rs | 6 +++--- src/test/compile-fail/E0259.rs | 1 + src/test/ui/suggestions/auxiliary/m1.rs | 11 +++++++++++ src/test/ui/suggestions/auxiliary/m2.rs | 11 +++++++++++ src/test/ui/suggestions/extern-crate-rename.rs | 18 ++++++++++++++++++ .../ui/suggestions/extern-crate-rename.stderr | 15 +++++++++++++++ 9 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/auxiliary/m1.rs create mode 100644 src/test/ui/suggestions/auxiliary/m2.rs create mode 100644 src/test/ui/suggestions/extern-crate-rename.rs create mode 100644 src/test/ui/suggestions/extern-crate-rename.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a10bce2934226..b30fc38fcbcdf 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -250,7 +250,7 @@ impl<'a> Resolver<'a> { } } - ItemKind::ExternCrate(_) => { + ItemKind::ExternCrate(as_name) => { self.crate_loader.process_item(item, &self.definitions); // n.b. we don't need to look at the path option here, because cstore already did @@ -265,7 +265,7 @@ impl<'a> Resolver<'a> { id: item.id, parent, imported_module: Cell::new(Some(module)), - subclass: ImportDirectiveSubclass::ExternCrate, + subclass: ImportDirectiveSubclass::ExternCrate(as_name), span: item.span, module_path: Vec::new(), vis: Cell::new(vis), diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index a66d1ce0859b7..5820acf1b9006 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -120,7 +120,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { _ if directive.used.get() || directive.vis.get() == ty::Visibility::Public || directive.span.source_equal(&DUMMY_SP) => {} - ImportDirectiveSubclass::ExternCrate => { + ImportDirectiveSubclass::ExternCrate(_) => { resolver.maybe_unused_extern_crates.push((directive.id, directive.span)); } ImportDirectiveSubclass::MacroUse => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index bed9f37c5157f..c4185e9080127 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1118,7 +1118,7 @@ impl<'a> NameBinding<'a> { match self.kind { NameBindingKind::Import { directive: &ImportDirective { - subclass: ImportDirectiveSubclass::ExternCrate, .. + subclass: ImportDirectiveSubclass::ExternCrate(_), .. }, .. } => true, _ => false, @@ -1132,6 +1132,15 @@ impl<'a> NameBinding<'a> { } } + fn is_renamed_extern_crate(&self) -> bool { + if let NameBindingKind::Import { directive, ..} = self.kind { + if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass { + return true; + } + } + false + } + fn is_glob_import(&self) -> bool { match self.kind { NameBindingKind::Import { directive, .. } => directive.is_glob(), @@ -3700,7 +3709,8 @@ impl<'a> Resolver<'a> { let cm = self.session.codemap(); let rename_msg = "You can use `as` to change the binding name of the import"; - if let Ok(snippet) = cm.span_to_snippet(binding.span) { + if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span), + binding.is_renamed_extern_crate()) { err.span_suggestion(binding.span, rename_msg, format!("{} as Other{}", snippet, name)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index b85bf18ea800c..bcbabd700946a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -23,7 +23,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::def::*; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::ast::{Ident, SpannedIdent, NodeId}; +use syntax::ast::{Ident, Name, SpannedIdent, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::parse::token; @@ -48,7 +48,7 @@ pub enum ImportDirectiveSubclass<'a> { max_vis: Cell, // The visibility of the greatest reexport. // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors. }, - ExternCrate, + ExternCrate(Option), MacroUse, } @@ -923,7 +923,7 @@ fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> St match *subclass { SingleImport { source, .. } => source.to_string(), GlobImport { .. } => "*".to_string(), - ExternCrate => "".to_string(), + ExternCrate(_) => "".to_string(), MacroUse => "#[macro_use]".to_string(), } } diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs index c285c4d9e00c1..e125cc0c19c37 100644 --- a/src/test/compile-fail/E0259.rs +++ b/src/test/compile-fail/E0259.rs @@ -18,5 +18,6 @@ extern crate libc as alloc; //~^ ERROR E0259 //~| NOTE `alloc` reimported here //~| NOTE `alloc` must be defined only once in the type namespace of this module +//~| NOTE You can use `as` to change the binding name of the import fn main() {} diff --git a/src/test/ui/suggestions/auxiliary/m1.rs b/src/test/ui/suggestions/auxiliary/m1.rs new file mode 100644 index 0000000000000..b61667cfd882c --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/m1.rs @@ -0,0 +1,11 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn foo() {} diff --git a/src/test/ui/suggestions/auxiliary/m2.rs b/src/test/ui/suggestions/auxiliary/m2.rs new file mode 100644 index 0000000000000..94ff5e4497fe9 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/m2.rs @@ -0,0 +1,11 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn bar() {} diff --git a/src/test/ui/suggestions/extern-crate-rename.rs b/src/test/ui/suggestions/extern-crate-rename.rs new file mode 100644 index 0000000000000..b3fa5871a82f5 --- /dev/null +++ b/src/test/ui/suggestions/extern-crate-rename.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:m1.rs +// aux-build:m2.rs + + +extern crate m1; +extern crate m2 as m1; + +fn main() {} diff --git a/src/test/ui/suggestions/extern-crate-rename.stderr b/src/test/ui/suggestions/extern-crate-rename.stderr new file mode 100644 index 0000000000000..c15e238e8b0a3 --- /dev/null +++ b/src/test/ui/suggestions/extern-crate-rename.stderr @@ -0,0 +1,15 @@ +error[E0259]: the name `m1` is defined multiple times + --> $DIR/extern-crate-rename.rs:16:1 + | +15 | extern crate m1; + | ---------------- previous import of the extern crate `m1` here +16 | extern crate m2 as m1; + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `m1` reimported here + | You can use `as` to change the binding name of the import + | + = note: `m1` must be defined only once in the type namespace of this module + +error: aborting due to previous error +