1
Fork 0

Add suggestion for duplicated import.

This commit adds a suggestion when a import is duplicated (ie. the same name
is used twice trying to import the same thing) to remove the second
import.
This commit is contained in:
David Wood 2019-01-29 13:34:40 +01:00
parent a21bd75688
commit 1595163356
No known key found for this signature in database
GPG key ID: 01760B4F9F53F154
18 changed files with 570 additions and 111 deletions

View file

@ -238,12 +238,14 @@ impl<'a> Resolver<'a> {
macro_ns: Cell::new(None),
},
type_ns_only,
nested,
};
self.add_import_directive(
module_path,
subclass,
use_tree.span,
id,
item,
root_span,
item.id,
vis,
@ -260,6 +262,7 @@ impl<'a> Resolver<'a> {
subclass,
use_tree.span,
id,
item,
root_span,
item.id,
vis,
@ -379,6 +382,9 @@ impl<'a> Resolver<'a> {
source: orig_name,
target: ident,
},
has_attributes: !item.attrs.is_empty(),
use_span_with_attributes: item.span_with_attributes(),
use_span: item.span,
root_span: item.span,
span: item.span,
module_path: Vec::new(),
@ -824,6 +830,9 @@ impl<'a> Resolver<'a> {
parent_scope: parent_scope.clone(),
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
subclass: ImportDirectiveSubclass::MacroUse,
use_span_with_attributes: item.span_with_attributes(),
has_attributes: !item.attrs.is_empty(),
use_span: item.span,
root_span: span,
span,
module_path: Vec::new(),

View file

@ -63,7 +63,7 @@ use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use syntax_pos::{BytePos, Span, DUMMY_SP, MultiSpan};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use std::cell::{Cell, RefCell};
@ -1228,6 +1228,16 @@ enum NameBindingKind<'a> {
},
}
impl<'a> NameBindingKind<'a> {
/// Is this a name binding of a import?
fn is_import(&self) -> bool {
match *self {
NameBindingKind::Import { .. } => true,
_ => false,
}
}
}
struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>);
struct UseError<'a> {
@ -5134,66 +5144,237 @@ impl<'a> Resolver<'a> {
);
// See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import;
let directive = match (&new_binding.kind, &old_binding.kind) {
(NameBindingKind::Import { directive, .. }, _) if !new_binding.span.is_dummy() =>
Some((directive, new_binding.span)),
(_, NameBindingKind::Import { directive, .. }) if !old_binding.span.is_dummy() =>
Some((directive, old_binding.span)),
// If there are two imports where one or both have attributes then prefer removing the
// import without attributes.
(Import { directive: new, .. }, Import { directive: old, .. }) if {
!new_binding.span.is_dummy() && !old_binding.span.is_dummy() &&
(new.has_attributes || old.has_attributes)
} => {
if old.has_attributes {
Some((new, new_binding.span, true))
} else {
Some((old, old_binding.span, true))
}
},
// Otherwise prioritize the new binding.
(Import { directive, .. }, other) if !new_binding.span.is_dummy() =>
Some((directive, new_binding.span, other.is_import())),
(other, Import { directive, .. }) if !old_binding.span.is_dummy() =>
Some((directive, old_binding.span, other.is_import())),
_ => None,
};
if let Some((directive, binding_span)) = directive {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
format!("Other{}", name)
} else {
format!("other_{}", name)
};
let mut suggestion = None;
match directive.subclass {
ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } =>
suggestion = Some(format!("self as {}", suggested_name)),
ImportDirectiveSubclass::SingleImport { source, .. } => {
if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
.map(|pos| pos as usize) {
if let Ok(snippet) = self.session.source_map()
.span_to_snippet(binding_span) {
if pos <= snippet.len() {
suggestion = Some(format!(
"{} as {}{}",
&snippet[..pos],
suggested_name,
if snippet.ends_with(";") { ";" } else { "" }
))
}
}
}
}
ImportDirectiveSubclass::ExternCrate { source, target, .. } =>
suggestion = Some(format!(
"extern crate {} as {};",
source.unwrap_or(target.name),
suggested_name,
)),
_ => unreachable!(),
}
// Check if the target of the use for both bindings is the same.
let duplicate = new_binding.def().opt_def_id() == old_binding.def().opt_def_id();
let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
let from_item = self.extern_prelude.get(&ident)
.map(|entry| entry.introduced_by_item)
.unwrap_or(true);
// Only suggest removing an import if both bindings are to the same def, if both spans
// aren't dummy spans. Further, if both bindings are imports, then the ident must have
// been introduced by a item.
let should_remove_import = duplicate && !has_dummy_span &&
((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
let rename_msg = "you can use `as` to change the binding name of the import";
if let Some(suggestion) = suggestion {
match directive {
Some((directive, span, true)) if should_remove_import && directive.is_nested() =>
self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span),
Some((directive, _, true)) if should_remove_import && !directive.is_glob() => {
// Simple case - remove the entire import. Due to the above match arm, this can
// only be a single use so just remove it entirely.
err.span_suggestion(
binding_span,
rename_msg,
suggestion,
directive.use_span_with_attributes,
"remove unnecessary import",
String::new(),
Applicability::MaybeIncorrect,
);
} else {
err.span_label(binding_span, rename_msg);
}
},
Some((directive, span, _)) =>
self.add_suggestion_for_rename_of_use(&mut err, name, directive, span),
_ => {},
}
err.emit();
self.name_already_seen.insert(name, span);
}
/// This function adds a suggestion to change the binding name of a new import that conflicts
/// with an existing import.
///
/// ```ignore (diagnostic)
/// help: you can use `as` to change the binding name of the import
/// |
/// LL | use foo::bar as other_bar;
/// | ^^^^^^^^^^^^^^^^^^^^^
/// ```
fn add_suggestion_for_rename_of_use(
&self,
err: &mut DiagnosticBuilder<'_>,
name: Symbol,
directive: &ImportDirective<'_>,
binding_span: Span,
) {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
format!("Other{}", name)
} else {
format!("other_{}", name)
};
let mut suggestion = None;
match directive.subclass {
ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } =>
suggestion = Some(format!("self as {}", suggested_name)),
ImportDirectiveSubclass::SingleImport { source, .. } => {
if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
.map(|pos| pos as usize) {
if let Ok(snippet) = self.session.source_map()
.span_to_snippet(binding_span) {
if pos <= snippet.len() {
suggestion = Some(format!(
"{} as {}{}",
&snippet[..pos],
suggested_name,
if snippet.ends_with(";") { ";" } else { "" }
))
}
}
}
}
ImportDirectiveSubclass::ExternCrate { source, target, .. } =>
suggestion = Some(format!(
"extern crate {} as {};",
source.unwrap_or(target.name),
suggested_name,
)),
_ => unreachable!(),
}
let rename_msg = "you can use `as` to change the binding name of the import";
if let Some(suggestion) = suggestion {
err.span_suggestion(
binding_span,
rename_msg,
suggestion,
Applicability::MaybeIncorrect,
);
} else {
err.span_label(binding_span, rename_msg);
}
}
/// This function adds a suggestion to remove a unnecessary binding from an import that is
/// nested. In the following example, this function will be invoked to remove the `a` binding
/// in the second use statement:
///
/// ```ignore (diagnostic)
/// use issue_52891::a;
/// use issue_52891::{d, a, e};
/// ```
///
/// The following suggestion will be added:
///
/// ```ignore (diagnostic)
/// use issue_52891::{d, a, e};
/// ^-- help: remove unnecessary import
/// ```
///
/// If the nested use contains only one import then the suggestion will remove the entire
/// line.
///
/// It is expected that the directive provided is a nested import - this isn't checked by the
/// function. If this invariant is not upheld, this function's behaviour will be unexpected
/// as characters expected by span manipulations won't be present.
fn add_suggestion_for_duplicate_nested_use(
&self,
err: &mut DiagnosticBuilder<'_>,
directive: &ImportDirective<'_>,
binding_span: Span,
) {
assert!(directive.is_nested());
let message = "remove unnecessary import";
let source_map = self.session.source_map();
// Two examples will be used to illustrate the span manipulations we're doing:
//
// - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
// `a` and `directive.use_span` is `issue_52891::{d, a, e};`.
// - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
// `a` and `directive.use_span` is `issue_52891::{d, e, a};`.
// Find the span of everything after the binding.
// ie. `a, e};` or `a};`
let binding_until_end = binding_span.with_hi(directive.use_span.hi());
// Find everything after the binding but not including the binding.
// ie. `, e};` or `};`
let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
// Keep characters in the span until we encounter something that isn't a comma or
// whitespace.
// ie. `, ` or ``.
//
// Also note whether a closing brace character was encountered. If there
// was, then later go backwards to remove any trailing commas that are left.
let mut found_closing_brace = false;
let after_binding_until_next_binding = source_map.span_take_while(
after_binding_until_end,
|&ch| {
if ch == '}' { found_closing_brace = true; }
ch == ' ' || ch == ','
}
);
// Combine the two spans.
// ie. `a, ` or `a`.
//
// Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
let span = binding_span.with_hi(after_binding_until_next_binding.hi());
// If there was a closing brace then identify the span to remove any trailing commas from
// previous imports.
if found_closing_brace {
if let Ok(prev_source) = source_map.span_to_prev_source(span) {
// `prev_source` will contain all of the source that came before the span.
// Then split based on a command and take the first (ie. closest to our span)
// snippet. In the example, this is a space.
let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
if prev_comma.len() > 1 && prev_starting_brace.len() > 1 {
let prev_comma = prev_comma.first().unwrap();
let prev_starting_brace = prev_starting_brace.first().unwrap();
// If the amount of source code before the comma is greater than
// the amount of source code before the starting brace then we've only
// got one item in the nested item (eg. `issue_52891::{self}`).
if prev_comma.len() > prev_starting_brace.len() {
// So just remove the entire line...
err.span_suggestion(
directive.use_span_with_attributes,
message,
String::new(),
Applicability::MaybeIncorrect,
);
return;
}
let span = span.with_lo(BytePos(
// Take away the number of bytes for the characters we've found and an
// extra for the comma.
span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
));
err.span_suggestion(
span, message, String::new(), Applicability::MaybeIncorrect,
);
return;
}
}
}
err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable);
}
fn extern_prelude_get(&mut self, ident: Ident, speculative: bool)
-> Option<&'a NameBinding<'a>> {
if ident.is_path_segment_keyword() {

View file

@ -18,7 +18,7 @@ use rustc::hir::def::*;
use rustc::session::DiagnosticMessageId;
use rustc::util::nodemap::FxHashSet;
use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::symbol::keywords;
@ -42,6 +42,8 @@ pub enum ImportDirectiveSubclass<'a> {
target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>,
/// `true` for `...::{self [as target]}` imports, `false` otherwise.
type_ns_only: bool,
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
nested: bool,
},
GlobImport {
is_prelude: bool,
@ -78,6 +80,15 @@ crate struct ImportDirective<'a> {
/// `UseTree` node.
pub root_id: NodeId,
/// Span of the entire use statement.
pub use_span: Span,
/// Span of the entire use statement with attributes.
pub use_span_with_attributes: Span,
/// Did the use statement have any attributes?
pub has_attributes: bool,
/// Span of this use tree.
pub span: Span,
@ -98,6 +109,13 @@ impl<'a> ImportDirective<'a> {
match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false }
}
pub fn is_nested(&self) -> bool {
match self.subclass {
ImportDirectiveSubclass::SingleImport { nested, .. } => nested,
_ => false
}
}
crate fn crate_lint(&self) -> CrateLint {
CrateLint::UsePath { root_id: self.root_id, root_span: self.root_span }
}
@ -390,6 +408,7 @@ impl<'a> Resolver<'a> {
subclass: ImportDirectiveSubclass<'a>,
span: Span,
id: NodeId,
item: &ast::Item,
root_span: Span,
root_id: NodeId,
vis: ty::Visibility,
@ -402,6 +421,9 @@ impl<'a> Resolver<'a> {
subclass,
span,
id,
use_span: item.span,
use_span_with_attributes: item.span_with_attributes(),
has_attributes: !item.attrs.is_empty(),
root_span,
root_id,
vis: Cell::new(vis),
@ -787,7 +809,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
let (source, target, source_bindings, target_bindings, type_ns_only) =
match directive.subclass {
SingleImport { source, target, ref source_bindings,
ref target_bindings, type_ns_only } =>
ref target_bindings, type_ns_only, .. } =>
(source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { .. } => {
self.resolve_glob_import(directive);
@ -908,7 +930,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
let (ident, target, source_bindings, target_bindings, type_ns_only) =
match directive.subclass {
SingleImport { source, target, ref source_bindings,
ref target_bindings, type_ns_only } =>
ref target_bindings, type_ns_only, .. } =>
(source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { is_prelude, ref max_vis } => {
if directive.module_path.len() <= 1 {

View file

@ -2164,6 +2164,13 @@ pub struct Item {
pub tokens: Option<TokenStream>,
}
impl Item {
/// Return the span that encompasses the attributes.
pub fn span_with_attributes(&self) -> Span {
self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span()))
}
}
/// A function header.
///
/// All the information between the visibility and the name of the function is

View file

@ -4,13 +4,12 @@ error[E0252]: the name `X` is defined multiple times
LL | pub use self::bar::X;
| ------------ previous import of the type `X` here
LL | use self::bar::X;
| ^^^^^^^^^^^^ `X` reimported here
| ----^^^^^^^^^^^^-
| | |
| | `X` reimported here
| help: remove unnecessary import
|
= note: `X` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use self::bar::X as OtherX;
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -10,15 +10,13 @@ error[E0252]: the name `fmt` is defined multiple times
--> $DIR/E0430.rs:1:22
|
LL | use std::fmt::{self, self}; //~ ERROR E0430
| ---- ^^^^ `fmt` reimported here
| |
| ------^^^^
| | | |
| | | `fmt` reimported here
| | help: remove unnecessary import
| previous import of the module `fmt` here
|
= note: `fmt` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use std::fmt::{self, self as other_fmt}; //~ ERROR E0430
| ^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -4,13 +4,12 @@ error[E0252]: the name `foo` is defined multiple times
LL | use a::foo;
| ------ previous import of the value `foo` here
LL | use a::foo; //~ ERROR the name `foo` is defined multiple times
| ^^^^^^ `foo` reimported here
| ----^^^^^^-
| | |
| | `foo` reimported here
| help: remove unnecessary import
|
= note: `foo` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use a::foo as other_foo; //~ ERROR the name `foo` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^
error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module)
--> $DIR/duplicate.rs:46:15

View file

@ -0,0 +1,33 @@
pub mod a {
pub mod inner {
}
}
pub mod b {
pub mod inner {
}
}
pub mod c {}
pub mod d {}
pub mod e {}
pub mod f {}
pub mod g {}
pub mod h {}
pub mod i {}
pub mod j {}
pub mod k {}
pub mod l {}
pub mod m {}
pub mod n {}

View file

@ -4,13 +4,12 @@ error[E0252]: the name `Arc` is defined multiple times
LL | use std::sync::{self, Arc};
| --- previous import of the type `Arc` here
LL | use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times
| ^^^^^^^^^^^^^^ `Arc` reimported here
| ----^^^^^^^^^^^^^^-
| | |
| | `Arc` reimported here
| help: remove unnecessary import
|
= note: `Arc` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use std::sync::Arc as OtherArc; //~ ERROR the name `Arc` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0252]: the name `sync` is defined multiple times
--> $DIR/issue-26886.rs:4:5
@ -19,13 +18,12 @@ LL | use std::sync::{self, Arc};
| ---- previous import of the module `sync` here
...
LL | use std::sync; //~ ERROR the name `sync` is defined multiple times
| ^^^^^^^^^ `sync` reimported here
| ----^^^^^^^^^-
| | |
| | `sync` reimported here
| help: remove unnecessary import
|
= note: `sync` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use std::sync as other_sync; //~ ERROR the name `sync` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -2,15 +2,13 @@ error[E0252]: the name `A` is defined multiple times
--> $DIR/import-twice.rs:6:14
|
LL | use foo::{A, A};
| - ^ `A` reimported here
| |
| ---^
| || |
| || `A` reimported here
| |help: remove unnecessary import
| previous import of the type `A` here
|
= note: `A` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use foo::{A, A as OtherA};
| ^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,37 @@
// aux-build:issue-52891.rs
// run-rustfix
#![allow(warnings)]
extern crate issue_52891;
// Check that we don't suggest renaming duplicate imports but instead
// suggest removing one.
use issue_52891::a;
//~ ERROR `a` is defined multiple times
use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times
use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times
use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times
use issue_52891::{//~ ERROR `a` is defined multiple times
h,
i};
use issue_52891::{j,
//~ ERROR `a` is defined multiple times
k};
use issue_52891::{l,
m}; //~ ERROR `a` is defined multiple times
use issue_52891::a::inner;
use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times
//~^ ERROR `issue_52891` is defined multiple times
#[macro_use]
use issue_52891::n; //~ ERROR `n` is defined multiple times
fn main() {}

View file

@ -0,0 +1,38 @@
// aux-build:issue-52891.rs
// run-rustfix
#![allow(warnings)]
extern crate issue_52891;
// Check that we don't suggest renaming duplicate imports but instead
// suggest removing one.
use issue_52891::a;
use issue_52891::a; //~ ERROR `a` is defined multiple times
use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times
use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times
use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times
use issue_52891::{a, //~ ERROR `a` is defined multiple times
h,
i};
use issue_52891::{j,
a, //~ ERROR `a` is defined multiple times
k};
use issue_52891::{l,
m,
a}; //~ ERROR `a` is defined multiple times
use issue_52891::a::inner;
use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times
use issue_52891::{self};
//~^ ERROR `issue_52891` is defined multiple times
use issue_52891::n;
#[macro_use]
use issue_52891::n; //~ ERROR `n` is defined multiple times
fn main() {}

View file

@ -0,0 +1,145 @@
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:12:5
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
LL | use issue_52891::a; //~ ERROR `a` is defined multiple times
| ----^^^^^^^^^^^^^^-
| | |
| | `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:14:19
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times
| ^--
| |
| `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:15:22
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times
| ^--
| |
| `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:16:25
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times
| --^
| | |
| | `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:18:19
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | use issue_52891::{a, //~ ERROR `a` is defined multiple times
| ^--
| |
| `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:22:5
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | a, //~ ERROR `a` is defined multiple times
| ^--
| |
| `a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `a` is defined multiple times
--> $DIR/issue-52891.rs:26:5
|
LL | use issue_52891::a;
| -------------- previous import of the module `a` here
...
LL | m,
| ______-
LL | | a}; //~ ERROR `a` is defined multiple times
| | -
| | |
| |_____`a` reimported here
| help: remove unnecessary import
|
= note: `a` must be defined only once in the type namespace of this module
error[E0252]: the name `inner` is defined multiple times
--> $DIR/issue-52891.rs:29:5
|
LL | use issue_52891::a::inner;
| --------------------- previous import of the module `inner` here
LL | use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here
|
= note: `inner` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0254]: the name `issue_52891` is defined multiple times
--> $DIR/issue-52891.rs:31:19
|
LL | extern crate issue_52891;
| ------------------------- previous import of the extern crate `issue_52891` here
...
LL | use issue_52891::{self};
| ------------------^^^^--
| | |
| | `issue_52891` reimported here
| help: remove unnecessary import
|
= note: `issue_52891` must be defined only once in the type namespace of this module
error[E0252]: the name `n` is defined multiple times
--> $DIR/issue-52891.rs:36:5
|
LL | use issue_52891::n;
| -------------------
| | |
| | previous import of the module `n` here
| help: remove unnecessary import
LL | #[macro_use]
LL | use issue_52891::n; //~ ERROR `n` is defined multiple times
| ^^^^^^^^^^^^^^ `n` reimported here
|
= note: `n` must be defined only once in the type namespace of this module
error: aborting due to 10 previous errors
Some errors occurred: E0252, E0254.
For more information about an error, try `rustc --explain E0252`.

View file

@ -1,17 +1,16 @@
error[E0259]: the name `derive_a` is defined multiple times
--> $DIR/shadow.rs:6:1
|
LL | extern crate derive_a;
| ---------------------- previous import of the extern crate `derive_a` here
LL | #[macro_use]
LL | extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^^ `derive_a` reimported here
LL | extern crate derive_a;
| ---------------------- previous import of the extern crate `derive_a` here
LL | / #[macro_use]
LL | | extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
| | ^^^^^^^^^^^^^^^^^^^^^-
| |_|____________________|
| | help: remove unnecessary import
| `derive_a` reimported here
|
= note: `derive_a` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | extern crate derive_a as other_derive_a; //~ ERROR the name `derive_a` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -4,13 +4,12 @@ error[E0252]: the name `transmute` is defined multiple times
LL | use std::mem::transmute;
| ------------------- previous import of the value `transmute` here
LL | use std::mem::transmute;
| ^^^^^^^^^^^^^^^^^^^ `transmute` reimported here
| ----^^^^^^^^^^^^^^^^^^^-
| | |
| | `transmute` reimported here
| help: remove unnecessary import
|
= note: `transmute` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use std::mem::transmute as other_transmute;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -4,13 +4,12 @@ error[E0254]: the name `core` is defined multiple times
LL | extern crate core;
| ------------------ previous import of the extern crate `core` here
LL | use core;
| ^^^^ `core` reimported here
| ----^^^^-
| | |
| | `core` reimported here
| help: remove unnecessary import
|
= note: `core` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use core as other_core;
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -20,13 +20,12 @@ LL | self,
| ---- previous import of the module `bar` here
...
LL | self
| ^^^^ `bar` reimported here
| ^^^^
| |
| `bar` reimported here
| help: remove unnecessary import
|
= note: `bar` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | self as other_bar
|
error: aborting due to 3 previous errors

View file

@ -4,13 +4,12 @@ error[E0252]: the name `mem` is defined multiple times
LL | use std::{mem, ptr};
| --- previous import of the module `mem` here
LL | use std::mem; //~ ERROR the name `mem` is defined multiple times
| ^^^^^^^^ `mem` reimported here
| ----^^^^^^^^-
| | |
| | `mem` reimported here
| help: remove unnecessary import
|
= note: `mem` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use std::mem as other_mem; //~ ERROR the name `mem` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error