about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-08-13 12:32:01 +0200
committerCamille GILLOT <gillot.camille@gmail.com>2022-10-13 16:50:24 +0000
commit112ce807261d46befe78b947944c02ecca829a7d (patch)
tree92f248a823155b1ccc267b652ec2726f50eaaa07
parent4891d57f7aab37b5d6a84f2901c0bb8903111d53 (diff)
downloadrust-112ce807261d46befe78b947944c02ecca829a7d.tar.gz
rust-112ce807261d46befe78b947944c02ecca829a7d.zip
Report duplicate definition in impls with overlap check.
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs40
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-2.stderr8
-rw-r--r--src/test/ui/associated-item/impl-duplicate-methods.rs (renamed from src/test/ui/impl-duplicate-methods.rs)2
-rw-r--r--src/test/ui/associated-item/impl-duplicate-methods.stderr11
-rw-r--r--src/test/ui/error-codes/E0201.rs2
-rw-r--r--src/test/ui/error-codes/E0201.stderr9
-rw-r--r--src/test/ui/impl-duplicate-methods.stderr11
-rw-r--r--src/test/ui/issues/issue-4265.stderr8
-rw-r--r--src/test/ui/methods/method-macro-backtrace.stderr8
10 files changed, 66 insertions, 74 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);
-            }
-        }
-    }
-}
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 f4efd131248..0b96a6bd7c0 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
index adb09d7f56e..328d54d5ac4 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 00000000000..6f753845ac8
--- /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 adefd4bcd46..04b37091b2f 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 f72145a8244..608ff691776 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 c19702a5bf0..00000000000
--- 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 27e83d49574..8c7303f3c3c 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 7ae00835c96..dd616c4a5e7 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`.