about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs3
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs13
-rw-r--r--compiler/rustc_resolve/src/late.rs33
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-3.rs1
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-3.stderr18
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names.stderr14
-rw-r--r--src/test/ui/error-codes/E0201.stderr30
-rw-r--r--src/test/ui/hygiene/impl_items-2.rs26
-rw-r--r--src/test/ui/hygiene/impl_items-2.stderr15
-rw-r--r--src/test/ui/traits/issue-8153.stderr7
11 files changed, 137 insertions, 25 deletions
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index c499364056f..69155a422b0 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -197,6 +197,9 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
 
 /// 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) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 98982240af2..75c016af2f9 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1047,6 +1047,19 @@ impl<'a> Resolver<'a> {
                 err.span_label(trait_item_span, "item in trait");
                 err
             }
+            ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
+                let mut err = struct_span_err!(
+                    self.session,
+                    span,
+                    E0201,
+                    "duplicate definitions with name `{}`:",
+                    name,
+                );
+                err.span_label(old_span, "previous definition here");
+                err.span_label(trait_item_span, "item in trait");
+                err.span_label(span, "duplicate definition");
+                err
+            }
             ResolutionError::InvalidAsmSym => {
                 let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
                 err.span_label(span, "is a local variable");
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 431507e8e0f..9fc8401fa07 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2619,8 +2619,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                         this.with_current_self_type(self_type, |this| {
                                             this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
                                                 debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
+                                                let mut seen_trait_items = Default::default();
                                                 for item in impl_items {
-                                                    this.resolve_impl_item(&**item);
+                                                    this.resolve_impl_item(&**item, &mut seen_trait_items);
                                                 }
                                             });
                                         });
@@ -2634,7 +2635,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         );
     }
 
-    fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
+    fn resolve_impl_item(
+        &mut self,
+        item: &'ast AssocItem,
+        seen_trait_items: &mut FxHashMap<DefId, Span>,
+    ) {
         use crate::ResolutionError::*;
         match &item.kind {
             AssocItemKind::Const(_, ty, default) => {
@@ -2647,6 +2652,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     &item.kind,
                     ValueNS,
                     item.span,
+                    seen_trait_items,
                     |i, s, c| ConstNotMemberOfTrait(i, s, c),
                 );
 
@@ -2687,6 +2693,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             &item.kind,
                             ValueNS,
                             item.span,
+                            seen_trait_items,
                             |i, s, c| MethodNotMemberOfTrait(i, s, c),
                         );
 
@@ -2715,6 +2722,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                 &item.kind,
                                 TypeNS,
                                 item.span,
+                                seen_trait_items,
                                 |i, s, c| TypeNotMemberOfTrait(i, s, c),
                             );
 
@@ -2736,6 +2744,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         kind: &AssocItemKind,
         ns: Namespace,
         span: Span,
+        seen_trait_items: &mut FxHashMap<DefId, Span>,
         err: F,
     ) where
         F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
@@ -2768,7 +2777,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         };
 
         let res = binding.res();
-        let Res::Def(def_kind, _) = res else { bug!() };
+        let Res::Def(def_kind, id_in_trait) = res else { bug!() };
+
+        match seen_trait_items.entry(id_in_trait) {
+            Entry::Occupied(entry) => {
+                self.report_error(
+                    span,
+                    ResolutionError::TraitImplDuplicate {
+                        name: ident.name,
+                        old_span: *entry.get(),
+                        trait_item_span: binding.span,
+                    },
+                );
+                return;
+            }
+            Entry::Vacant(entry) => {
+                entry.insert(span);
+            }
+        };
+
         match (def_kind, kind) {
             (DefKind::AssocTy, AssocItemKind::TyAlias(..))
             | (DefKind::AssocFn, AssocItemKind::Fn(..))
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 9173c3692ce..4c9e14db3c4 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -236,6 +236,8 @@ enum ResolutionError<'a> {
         trait_item_span: Span,
         code: rustc_errors::DiagnosticId,
     },
+    /// Error E0201: multiple impl items for the same trait item.
+    TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
     /// Inline asm `sym` operand must refer to a `fn` or `static`.
     InvalidAsmSym,
 }
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.rs b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
index 6aa1b483eeb..3a70a2f943f 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
@@ -16,4 +16,5 @@ impl Foo for Baz {
 
 fn main() {
     let x: Baz::Bar = 5;
+    //~^ ERROR ambiguous associated type
 }
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
index 03782f66348..bf4bd634cf1 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
@@ -1,11 +1,21 @@
 error[E0201]: duplicate definitions with name `Bar`:
   --> $DIR/associated-item-duplicate-names-3.rs:14:5
    |
+LL |     type Bar;
+   |     --------- item in trait
+...
 LL |     type Bar = i16;
-   |     -------- previous definition of `Bar` here
+   |     --------------- previous definition here
 LL |     type Bar = u16;
-   |     ^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^ duplicate definition
 
-error: aborting due to previous error
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-item-duplicate-names-3.rs:18:12
+   |
+LL |     let x: Baz::Bar = 5;
+   |            ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0201`.
+Some errors have detailed explanations: E0201, E0223.
+For more information about an error, try `rustc --explain E0201`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names.stderr b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
index c9119c10271..f89ea6e57cc 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
@@ -1,18 +1,24 @@
 error[E0201]: duplicate definitions with name `Ty`:
   --> $DIR/associated-item-duplicate-names.rs:11:5
    |
+LL |     type Ty;
+   |     -------- item in trait
+...
 LL |     type Ty = ();
-   |     ------- previous definition of `Ty` here
+   |     ------------- previous definition here
 LL |     type Ty = usize;
-   |     ^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^ duplicate definition
 
 error[E0201]: duplicate definitions with name `BAR`:
   --> $DIR/associated-item-duplicate-names.rs:13:5
    |
+LL |     const BAR: u32;
+   |     --------------- item in trait
+...
 LL |     const BAR: u32 = 7;
-   |     -------------- previous definition of `BAR` here
+   |     ------------------- previous definition here
 LL |     const BAR: u32 = 8;
-   |     ^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^^^^ duplicate definition
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr
index 94e06894144..f72145a8244 100644
--- a/src/test/ui/error-codes/E0201.stderr
+++ b/src/test/ui/error-codes/E0201.stderr
@@ -1,27 +1,33 @@
-error[E0201]: duplicate definitions with name `bar`:
-  --> $DIR/E0201.rs:5:5
-   |
-LL |     fn bar(&self) -> bool { self.0 > 5 }
-   |     --------------------- previous definition of `bar` here
-LL |     fn bar() {}
-   |     ^^^^^^^^ duplicate definition
-
 error[E0201]: duplicate definitions with name `baz`:
   --> $DIR/E0201.rs:17:5
    |
+LL |     fn baz(&self) -> bool;
+   |     ---------------------- item in trait
+...
 LL |     fn baz(&self) -> bool { true }
-   |     --------------------- previous definition of `baz` here
+   |     ------------------------------ previous definition here
 LL |     fn baz(&self) -> bool { self.0 > 5 }
-   |     ^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
 
 error[E0201]: duplicate definitions with name `Quux`:
   --> $DIR/E0201.rs:18:5
    |
+LL |     type Quux;
+   |     ---------- item in trait
+...
 LL |     type Quux = u32;
-   |     --------- previous definition of `Quux` here
+   |     ---------------- previous definition here
 ...
 LL |     type Quux = u32;
-   |     ^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^ duplicate definition
+
+error[E0201]: duplicate definitions with name `bar`:
+  --> $DIR/E0201.rs:5:5
+   |
+LL |     fn bar(&self) -> bool { self.0 > 5 }
+   |     --------------------- previous definition of `bar` here
+LL |     fn bar() {}
+   |     ^^^^^^^^ duplicate definition
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/hygiene/impl_items-2.rs b/src/test/ui/hygiene/impl_items-2.rs
new file mode 100644
index 00000000000..465e444aedb
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items-2.rs
@@ -0,0 +1,26 @@
+#![feature(decl_macro)]
+
+trait Trait {
+    fn foo() {}
+}
+
+macro trait_impl() {
+    fn foo() {}
+}
+
+// Check that we error on multiple impl items that resolve to the same trait item.
+impl Trait for i32 {
+    trait_impl!();
+    fn foo() {}
+    //~^ ERROR duplicate definitions with name `foo`: [E0201]
+}
+
+struct Type;
+
+// Check that we do not error with inherent impls.
+impl Type {
+    trait_impl!();
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/impl_items-2.stderr b/src/test/ui/hygiene/impl_items-2.stderr
new file mode 100644
index 00000000000..3c0ffeb1057
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items-2.stderr
@@ -0,0 +1,15 @@
+error[E0201]: duplicate definitions with name `foo`:
+  --> $DIR/impl_items-2.rs:14:5
+   |
+LL |     fn foo() {}
+   |     ----------- item in trait
+...
+LL |     fn foo() {}
+   |     ----------- previous definition here
+...
+LL |     fn foo() {}
+   |     ^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/traits/issue-8153.stderr b/src/test/ui/traits/issue-8153.stderr
index b76bbc0235f..ae214bb9e9b 100644
--- a/src/test/ui/traits/issue-8153.stderr
+++ b/src/test/ui/traits/issue-8153.stderr
@@ -1,10 +1,13 @@
 error[E0201]: duplicate definitions with name `bar`:
   --> $DIR/issue-8153.rs:11:5
    |
+LL |     fn bar(&self) -> isize;
+   |     ----------------------- item in trait
+...
 LL |     fn bar(&self) -> isize {1}
-   |     ---------------------- previous definition of `bar` here
+   |     -------------------------- previous definition here
 LL |     fn bar(&self) -> isize {2}
-   |     ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
 
 error: aborting due to previous error