diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3752d953f8afa..c5401ac3f5560 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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(), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 55d5cdedd6ddd..3973bc2ad62de 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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,64 +5144,235 @@ 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 { "" } - )) - } + // 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); + + 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( + directive.use_span_with_attributes, + "remove unnecessary import", + String::new(), + Applicability::MaybeIncorrect, + ); + }, + 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!(), } + 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); + } + } - 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::>(); + let prev_starting_brace = prev_source.rsplit('{').collect::>(); + 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.emit(); - self.name_already_seen.insert(name, span); + err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable); } fn extern_prelude_get(&mut self, ident: Ident, speculative: bool) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9a04c9d60b868..197cf7014db3d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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>>>, /// `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), @@ -784,7 +806,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); @@ -905,7 +927,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 { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index af521848e9057..4f3f5631cc39c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2164,6 +2164,13 @@ pub struct Item { pub tokens: Option, } +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 diff --git a/src/test/ui/double-type-import.stderr b/src/test/ui/double-type-import.stderr index 4bdee0c4c9f6c..c7288af13c278 100644 --- a/src/test/ui/double-type-import.stderr +++ b/src/test/ui/double-type-import.stderr @@ -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 diff --git a/src/test/ui/error-codes/E0430.stderr b/src/test/ui/error-codes/E0430.stderr index 0151cde887f1d..78e4e43ac2f3d 100644 --- a/src/test/ui/error-codes/E0430.stderr +++ b/src/test/ui/error-codes/E0430.stderr @@ -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 diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index acd66826fdfb7..29660d908e485 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -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 diff --git a/src/test/ui/issues/auxiliary/issue-52891.rs b/src/test/ui/issues/auxiliary/issue-52891.rs new file mode 100644 index 0000000000000..0759811832242 --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-52891.rs @@ -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 {} diff --git a/src/test/ui/issues/issue-26886.stderr b/src/test/ui/issues/issue-26886.stderr index 08faa9c9ca2c2..70dacb353fe07 100644 --- a/src/test/ui/issues/issue-26886.stderr +++ b/src/test/ui/issues/issue-26886.stderr @@ -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 diff --git a/src/test/ui/issues/issue-45829/import-twice.stderr b/src/test/ui/issues/issue-45829/import-twice.stderr index 374b809647e7a..2a1ac57651138 100644 --- a/src/test/ui/issues/issue-45829/import-twice.stderr +++ b/src/test/ui/issues/issue-45829/import-twice.stderr @@ -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 diff --git a/src/test/ui/issues/issue-52891.fixed b/src/test/ui/issues/issue-52891.fixed new file mode 100644 index 0000000000000..e694b5c9b154f --- /dev/null +++ b/src/test/ui/issues/issue-52891.fixed @@ -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() {} diff --git a/src/test/ui/issues/issue-52891.rs b/src/test/ui/issues/issue-52891.rs new file mode 100644 index 0000000000000..cd4b40629ab7f --- /dev/null +++ b/src/test/ui/issues/issue-52891.rs @@ -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() {} diff --git a/src/test/ui/issues/issue-52891.stderr b/src/test/ui/issues/issue-52891.stderr new file mode 100644 index 0000000000000..55d611070d9dc --- /dev/null +++ b/src/test/ui/issues/issue-52891.stderr @@ -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`. diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr index 103c78126a838..2dfe2a94c88e1 100644 --- a/src/test/ui/proc-macro/shadow.stderr +++ b/src/test/ui/proc-macro/shadow.stderr @@ -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 diff --git a/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr b/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr index 2852d122e5e4a..1b4b058b783ad 100644 --- a/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr +++ b/src/test/ui/resolve/resolve-conflict-import-vs-import.stderr @@ -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 diff --git a/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr index 012d3c3a7510f..e8679a3726d30 100644 --- a/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr +++ b/src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr @@ -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 diff --git a/src/test/ui/use/use-mod.stderr b/src/test/ui/use/use-mod.stderr index 9ab873b35989c..c23ab34eae678 100644 --- a/src/test/ui/use/use-mod.stderr +++ b/src/test/ui/use/use-mod.stderr @@ -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 diff --git a/src/test/ui/use/use-paths-as-items.stderr b/src/test/ui/use/use-paths-as-items.stderr index 5bcdf937d5698..00f468cdf316b 100644 --- a/src/test/ui/use/use-paths-as-items.stderr +++ b/src/test/ui/use/use-paths-as-items.stderr @@ -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