diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 03e076bf5ec89..c634a57b0b534 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -58,6 +58,37 @@ impl<'tcx> InherentOverlapChecker<'tcx> { == item2.ident(self.tcx).normalize_to_macros_2_0() } + fn check_for_duplicate_items_in_impl(&self, impl_: DefId) { + let impl_items = self.tcx.associated_items(impl_); + + let mut seen_items = FxHashMap::default(); + for impl_item in impl_items.in_definition_order() { + let span = self.tcx.def_span(impl_item.def_id); + let ident = impl_item.ident(self.tcx); + + let norm_ident = ident.normalize_to_macros_2_0(); + match seen_items.entry(norm_ident) { + Entry::Occupied(entry) => { + let former = entry.get(); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0592, + "duplicate definitions with name `{}`", + ident, + ); + err.span_label(span, format!("duplicate definitions for `{}`", ident)); + err.span_label(*former, format!("other definition for `{}`", ident)); + + err.emit(); + } + Entry::Vacant(entry) => { + entry.insert(span); + } + } + } + } + fn check_for_common_items_in_impls( &self, impl1: DefId, @@ -133,12 +164,6 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let impls = self.tcx.inherent_impls(id.def_id); - // If there is only one inherent impl block, - // there is nothing to overlap check it with - if impls.len() <= 1 { - return; - } - let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id()); let impls_items = impls @@ -152,6 +177,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> { const ALLOCATING_ALGO_THRESHOLD: usize = 500; if impls.len() < ALLOCATING_ALGO_THRESHOLD { for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { + self.check_for_duplicate_items_in_impl(impl1_def_id); + for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { if self.impls_have_common_items(impl_items1, impl_items2) { self.check_for_overlapping_inherent_impls( @@ -290,6 +317,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl_blocks.sort_unstable(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; + self.check_for_duplicate_items_in_impl(impl1_def_id); + for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; if self.impls_have_common_items(impl_items1, impl_items2) { diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 69155a422b062..a84257b939c52 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -11,7 +11,7 @@ use crate::constrained_generic_params as cgp; use min_specialization::check_min_specialization; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -19,8 +19,6 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Span, Symbol}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; - mod min_specialization; /// Checks that all the type/lifetime parameters on an impl also @@ -59,7 +57,6 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { for id in module.items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { enforce_impl_params_are_constrained(tcx, id.def_id.def_id); - enforce_impl_items_are_distinct(tcx, id.def_id.def_id); if min_specialization { check_min_specialization(tcx, id.def_id.def_id); } @@ -194,38 +191,3 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol } err.emit(); } - -/// Enforce that we do not have two items in an impl with the same name. -fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { - if tcx.impl_trait_ref(impl_def_id).is_some() { - return; - } - let mut seen_type_items = FxHashMap::default(); - let mut seen_value_items = FxHashMap::default(); - for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) { - let impl_item = tcx.associated_item(impl_item_ref); - let seen_items = match impl_item.kind { - ty::AssocKind::Type => &mut seen_type_items, - _ => &mut seen_value_items, - }; - let span = tcx.def_span(impl_item_ref); - let ident = impl_item.ident(tcx); - match seen_items.entry(ident.normalize_to_macros_2_0()) { - Occupied(entry) => { - let mut err = struct_span_err!( - tcx.sess, - span, - E0201, - "duplicate definitions with name `{}`:", - ident - ); - err.span_label(*entry.get(), format!("previous definition of `{}` here", ident)); - err.span_label(span, "duplicate definition"); - err.emit(); - } - Vacant(entry) => { - entry.insert(span); - } - } - } -} diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr index f4efd131248ce..0b96a6bd7c009 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr @@ -1,11 +1,11 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/associated-item-duplicate-names-2.rs:5:5 | LL | const bar: bool = true; - | --------------- previous definition of `bar` here + | --------------- other definition for `bar` LL | fn bar() {} - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/impl-duplicate-methods.rs b/src/test/ui/associated-item/impl-duplicate-methods.rs similarity index 57% rename from src/test/ui/impl-duplicate-methods.rs rename to src/test/ui/associated-item/impl-duplicate-methods.rs index adb09d7f56e93..328d54d5ac411 100644 --- a/src/test/ui/impl-duplicate-methods.rs +++ b/src/test/ui/associated-item/impl-duplicate-methods.rs @@ -3,7 +3,7 @@ struct Foo; impl Foo { fn orange(&self) {} fn orange(&self) {} - //~^ ERROR duplicate definition + //~^ ERROR duplicate definitions with name `orange` [E0592] } fn main() {} diff --git a/src/test/ui/associated-item/impl-duplicate-methods.stderr b/src/test/ui/associated-item/impl-duplicate-methods.stderr new file mode 100644 index 0000000000000..6f753845ac85a --- /dev/null +++ b/src/test/ui/associated-item/impl-duplicate-methods.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `orange` + --> $DIR/impl-duplicate-methods.rs:5:5 + | +LL | fn orange(&self) {} + | ---------------- other definition for `orange` +LL | fn orange(&self) {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `orange` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/error-codes/E0201.rs b/src/test/ui/error-codes/E0201.rs index adefd4bcd4600..04b37091b2f16 100644 --- a/src/test/ui/error-codes/E0201.rs +++ b/src/test/ui/error-codes/E0201.rs @@ -2,7 +2,7 @@ struct Foo(u8); impl Foo { fn bar(&self) -> bool { self.0 > 5 } - fn bar() {} //~ ERROR E0201 + fn bar() {} //~ ERROR E0592 } trait Baz { diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr index f72145a82447b..608ff69177694 100644 --- a/src/test/ui/error-codes/E0201.stderr +++ b/src/test/ui/error-codes/E0201.stderr @@ -21,14 +21,15 @@ LL | type Quux = u32; LL | type Quux = u32; | ^^^^^^^^^^^^^^^^ duplicate definition -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/E0201.rs:5:5 | LL | fn bar(&self) -> bool { self.0 > 5 } - | --------------------- previous definition of `bar` here + | --------------------- other definition for `bar` LL | fn bar() {} - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0201`. +Some errors have detailed explanations: E0201, E0592. +For more information about an error, try `rustc --explain E0201`. diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr deleted file mode 100644 index c19702a5bf0cf..0000000000000 --- a/src/test/ui/impl-duplicate-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0201]: duplicate definitions with name `orange`: - --> $DIR/impl-duplicate-methods.rs:5:5 - | -LL | fn orange(&self) {} - | ---------------- previous definition of `orange` here -LL | fn orange(&self) {} - | ^^^^^^^^^^^^^^^^ duplicate definition - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0201`. diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr index 27e83d4957493..8c7303f3c3c51 100644 --- a/src/test/ui/issues/issue-4265.stderr +++ b/src/test/ui/issues/issue-4265.stderr @@ -1,12 +1,12 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/issue-4265.rs:10:5 | LL | fn bar() { - | -------- previous definition of `bar` here + | -------- other definition for `bar` ... LL | fn bar() { - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr index 7ae00835c965d..dd616c4a5e75d 100644 --- a/src/test/ui/methods/method-macro-backtrace.stderr +++ b/src/test/ui/methods/method-macro-backtrace.stderr @@ -1,11 +1,11 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/method-macro-backtrace.rs:22:5 | LL | fn bar(&self) { } - | ------------- previous definition of `bar` here + | ------------- other definition for `bar` LL | fn bar(&self) { } - | ^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`.