From e1720d739625da90caa5a888549918683c897562 Mon Sep 17 00:00:00 2001 From: bohan Date: Mon, 7 Jul 2025 16:53:25 +0800 Subject: [PATCH] consider nested cases for duplicate RPITIT --- compiler/rustc_ty_utils/src/assoc.rs | 34 +++++++++---- ...tit-duplicate-associated-fn-with-nested.rs | 46 +++++++++++++++++ ...duplicate-associated-fn-with-nested.stderr | 49 +++++++++++++++++++ .../rpitit-duplicate-associated-fn.rs | 11 +++++ .../rpitit-duplicate-associated-fn.stderr | 33 ++++++++++++- 5 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs create mode 100644 tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 2fb3c5ff945af..6a9461f2b43a7 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 0000000000000..e3dc22c1992d5 --- /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>; + fn foo() -> impl Sized; + //~^ ERROR: the name `foo` is defined multiple times +} + +trait Bar { + fn foo() -> impl T>; + fn foo() -> impl T>; + //~^ ERROR: the name `foo` is defined multiple times +} + +struct S { + a: T +} + +trait Baz { + fn foo() -> S>>>; + fn foo() -> S>>>; + //~^ ERROR: the name `foo` is defined multiple times +} + +struct S1 { + a: T1, + b: T2 +} + +trait Qux { + fn foo() -> S1< + impl T>, + impl T>> + >; + fn foo() -> S1< + impl T>, + impl T>> + >; + //~^^^^ 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 0000000000000..f4e73dc17988b --- /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>; + | --------------------------------------------------------- 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>; + | --------------------------------------------------------- previous definition of the value `foo` here +LL | fn foo() -> impl T>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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>>>; + | ------------------------------------------------- previous definition of the value `foo` here +LL | fn foo() -> S>>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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>, +LL | | impl T>> +LL | | >; + | |__________- previous definition of the value `foo` here +LL | / fn foo() -> S1< +LL | | impl T>, +LL | | impl T>> +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 4fddd7c4ac8c6..6db0c88f6c005 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 b58e8136479c1..faa65f45d33cb 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`.