Skip to content

Commit d06174b

Browse files
committed
distinguish the duplicate item of rpitit
1 parent f0b67dd commit d06174b

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

compiler/rustc_ty_utils/src/assoc.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,39 @@ fn associated_types_for_impl_traits_in_associated_fn(
195195
match tcx.def_kind(parent_def_id) {
196196
DefKind::Trait => {
197197
if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
198-
let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id()));
198+
let def_path_id = |def_id: LocalDefId| tcx.item_name(def_id.to_def_id());
199+
let def_path_data = def_path_id(fn_def_id);
200+
201+
let (.., trait_item_refs) = tcx.hir_expect_item(parent_def_id).expect_trait();
202+
// The purpose of `disambiguator_idx` is to ensure there are
203+
// no duplicate `def_id` in certain cases, such as:
204+
// ```
205+
// trait Foo {
206+
// fn bar() -> impl Trait;
207+
// fn bar() -> impl Trait;
208+
// // ~~~~~~~~~~ It will generate the same ID if we don’t disambiguate it.
209+
// }
210+
// ```
211+
let disambiguator_idx = trait_item_refs
212+
.iter()
213+
.take_while(|item| item.id.owner_id.def_id != fn_def_id)
214+
.fold(0, |acc, item| {
215+
if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) {
216+
acc
217+
} else if def_path_id(item.id.owner_id.def_id) == def_path_data {
218+
tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator
219+
+ 1
220+
} else {
221+
acc
222+
}
223+
});
224+
225+
let data = DefPathData::AnonAssocTy(def_path_data);
199226
let mut visitor = RPITVisitor {
200227
tcx,
201228
synthetics: vec![],
202229
data,
203-
disambiguator: DisambiguatorState::with(parent_def_id, data, 0),
230+
disambiguator: DisambiguatorState::with(parent_def_id, data, disambiguator_idx),
204231
};
205232
visitor.visit_fn_ret_ty(output);
206233
tcx.arena.alloc_from_iter(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// issue#140796
2+
3+
trait Bar {
4+
fn method() -> impl Sized;
5+
fn method() -> impl Sized;
6+
//~^ ERROR: the name `method` is defined multiple times
7+
}
8+
9+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0428]: the name `method` is defined multiple times
2+
--> $DIR/rpitit-duplicate-associated-fn.rs:5:5
3+
|
4+
LL | fn method() -> impl Sized;
5+
| -------------------------- previous definition of the value `method` here
6+
LL | fn method() -> impl Sized;
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `method` redefined here
8+
|
9+
= note: `method` must be defined only once in the value namespace of this trait
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0428`.

0 commit comments

Comments
 (0)