diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/impl_wf_check.rs | 40 |
2 files changed, 36 insertions, 45 deletions
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 03e076bf5ec..c634a57b0b5 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 69155a422b0..a84257b939c 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); - } - } - } -} |
