about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-08 03:09:57 +0200
committerGitHub <noreply@github.com>2025-07-08 03:09:57 +0200
commita4e05e1f74fe258533ede9c41e43ff8c386615f8 (patch)
tree4fca362fb3063274e3614212c7f645a75165df90
parent40e1ccf458ae48eed859f72bd2172c2eaef41958 (diff)
parente1720d739625da90caa5a888549918683c897562 (diff)
downloadrust-a4e05e1f74fe258533ede9c41e43ff8c386615f8.tar.gz
rust-a4e05e1f74fe258533ede9c41e43ff8c386615f8.zip
Rollup merge of #143570 - bvanjoi:issue-143560, r=compiler-errors
consider nested cases for duplicate RPITIT

Fixes rust-lang/rust#143560

r? `@compiler-errors`

cc `@Zoxc`
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs34
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs46
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr49
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs11
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr33
5 files changed, 162 insertions, 11 deletions
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 2fb3c5ff945..6a9461f2b43 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -177,6 +177,17 @@ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
     }
 }
 
+struct DisambiguatorIdxVisitor {
+    depth: u32,
+}
+
+impl<'tcx> Visitor<'tcx> for DisambiguatorIdxVisitor {
+    fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result {
+        self.depth += 1;
+        intravisit::walk_opaque_ty(self, opaque)
+    }
+}
+
 /// Given an `fn_def_id` of a trait or a trait implementation:
 ///
 /// if `fn_def_id` is a function defined inside a trait, then it synthesizes
@@ -211,16 +222,19 @@ fn associated_types_for_impl_traits_in_associated_fn(
                 let disambiguator_idx = trait_item_refs
                     .iter()
                     .take_while(|item| item.id.owner_id.def_id != fn_def_id)
-                    .fold(0, |acc, item| {
-                        if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) {
-                            acc
-                        } else if def_path_id(item.id.owner_id.def_id) == def_path_data {
-                            tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator
-                                + 1
-                        } else {
-                            acc
-                        }
-                    });
+                    .filter(|item| {
+                        matches!(item.kind, hir::AssocItemKind::Fn { .. })
+                            && def_path_id(item.id.owner_id.def_id) == def_path_data
+                    })
+                    .last()
+                    .map(|item| {
+                        let output = tcx.hir_get_fn_output(item.id.owner_id.def_id).unwrap();
+                        let mut visitor = DisambiguatorIdxVisitor { depth: 0 };
+                        visitor.visit_fn_ret_ty(output);
+                        tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator
+                            + visitor.depth
+                    })
+                    .unwrap_or_default();
 
                 let data = DefPathData::AnonAssocTy(def_path_data);
                 let mut visitor = RPITVisitor {
diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs
new file mode 100644
index 00000000000..e3dc22c1992
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs
@@ -0,0 +1,46 @@
+// issue#143560
+
+trait T {
+    type Target;
+}
+
+trait Foo {
+    fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+    fn foo() -> impl Sized;
+    //~^ ERROR: the name `foo` is defined multiple times
+}
+
+trait Bar {
+    fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+    fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+    //~^ ERROR: the name `foo` is defined multiple times
+}
+
+struct S<T> {
+    a: T
+}
+
+trait Baz {
+    fn foo() -> S<impl T<Target = S<S<impl Sized>>>>;
+    fn foo() -> S<impl T<Target = S<S<impl Sized>>>>;
+    //~^ ERROR: the name `foo` is defined multiple times
+}
+
+struct S1<T1, T2> {
+    a: T1,
+    b: T2
+}
+
+trait Qux {
+    fn foo() -> S1<
+        impl T<Target = impl T<Target = impl Sized>>,
+        impl T<Target = impl T<Target = S<impl Sized>>>
+        >;
+    fn foo() -> S1<
+        impl T<Target = impl T<Target = impl Sized>>,
+        impl T<Target = impl T<Target = S<impl Sized>>>
+        >;
+    //~^^^^ ERROR: the name `foo` is defined multiple times
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr
new file mode 100644
index 00000000000..f4e73dc1798
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr
@@ -0,0 +1,49 @@
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:9:5
+   |
+LL |     fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+   |     --------------------------------------------------------- previous definition of the value `foo` here
+LL |     fn foo() -> impl Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:15:5
+   |
+LL |     fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+   |     --------------------------------------------------------- previous definition of the value `foo` here
+LL |     fn foo() -> impl T<Target = impl T<Target = impl Sized>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:25:5
+   |
+LL |     fn foo() -> S<impl T<Target = S<S<impl Sized>>>>;
+   |     ------------------------------------------------- previous definition of the value `foo` here
+LL |     fn foo() -> S<impl T<Target = S<S<impl Sized>>>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:39:5
+   |
+LL | /     fn foo() -> S1<
+LL | |         impl T<Target = impl T<Target = impl Sized>>,
+LL | |         impl T<Target = impl T<Target = S<impl Sized>>>
+LL | |         >;
+   | |__________- previous definition of the value `foo` here
+LL | /     fn foo() -> S1<
+LL | |         impl T<Target = impl T<Target = impl Sized>>,
+LL | |         impl T<Target = impl T<Target = S<impl Sized>>>
+LL | |         >;
+   | |__________^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs
index 4fddd7c4ac8..6db0c88f6c0 100644
--- a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs
+++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs
@@ -27,4 +27,15 @@ impl T for () {
     }
 }
 
+trait Baz {
+    fn foo();
+    fn foo() -> impl Sized;     //~ ERROR: the name `foo` is defined multiple times
+}
+
+trait Foo {
+    fn foo() -> impl Sized;
+    fn foo();                   //~ ERROR: the name `foo` is defined multiple times
+    fn foo() -> impl Sized;     //~ ERROR: the name `foo` is defined multiple times
+}
+
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr
index b58e8136479..faa65f45d33 100644
--- a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr
+++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr
@@ -8,6 +8,37 @@ LL |     fn method() -> impl Sized;
    |
    = note: `method` must be defined only once in the value namespace of this trait
 
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn.rs:32:5
+   |
+LL |     fn foo();
+   |     --------- previous definition of the value `foo` here
+LL |     fn foo() -> impl Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn.rs:37:5
+   |
+LL |     fn foo() -> impl Sized;
+   |     ----------------------- previous definition of the value `foo` here
+LL |     fn foo();
+   |     ^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
+error[E0428]: the name `foo` is defined multiple times
+  --> $DIR/rpitit-duplicate-associated-fn.rs:38:5
+   |
+LL |     fn foo() -> impl Sized;
+   |     ----------------------- previous definition of the value `foo` here
+LL |     fn foo();
+LL |     fn foo() -> impl Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here
+   |
+   = note: `foo` must be defined only once in the value namespace of this trait
+
 error[E0201]: duplicate definitions with name `method`:
   --> $DIR/rpitit-duplicate-associated-fn.rs:12:5
    |
@@ -47,7 +78,7 @@ LL |     fn method() -> impl Sized;
 LL | impl Bar for () {
    | ^^^^^^^^^^^^^^^ missing `method` in implementation
 
-error: aborting due to 4 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0046, E0201, E0428.
 For more information about an error, try `rustc --explain E0046`.