Skip to content

Commit 3bbc70a

Browse files
committed
Restrict param constraint suggestion
When encountering an associated item with a type param that could be constrained, do not look at the parent item if the type param comes from the associated item. Fix rust-lang#117209.
1 parent 6f65201 commit 3bbc70a

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

Diff for: compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,11 @@ impl<T> Trait<T> for X {
364364
};
365365
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
366366
// This will also work for `impl Trait`.
367-
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
368-
let generics = tcx.generics_of(body_owner_def_id);
369-
generics.type_param(param_ty, tcx).def_id
370-
} else {
367+
let ty::Param(param_ty) = proj_ty.self_ty().kind() else {
371368
return false;
372369
};
370+
let generics = tcx.generics_of(body_owner_def_id);
371+
let def_id = generics.type_param(param_ty, tcx).def_id;
373372
let Some(def_id) = def_id.as_local() else {
374373
return false;
375374
};
@@ -390,6 +389,10 @@ impl<T> Trait<T> for X {
390389
return true;
391390
}
392391
}
392+
if (param_ty.index as usize) >= generics.parent_count {
393+
// The param comes from the current item, do not look at the parent. (#117209)
394+
return false;
395+
}
393396
// If associated item, look to constrain the params of the trait/impl.
394397
let hir_id = match item {
395398
hir::Node::ImplItem(item) => item.hir_id(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use std::collections::HashMap;
2+
use std::hash::Hash;
3+
4+
trait LowT: Identify {}
5+
6+
trait Identify {
7+
type Id: Clone + Hash + PartialEq + Eq;
8+
fn identify(&self) -> Self::Id;
9+
}
10+
11+
struct MapStore<L, I>
12+
where
13+
L: LowT + Identify<Id = I>,
14+
{
15+
lows: HashMap<I, L>,
16+
}
17+
18+
impl<L, I> MapStore<L, I>
19+
where
20+
L: LowT + Identify<Id = I>,
21+
I: Clone + Hash + PartialEq + Eq,
22+
{
23+
fn remove_low(&mut self, low: &impl LowT) {
24+
let _low = self.lows.remove(low.identify()).unwrap(); //~ ERROR mismatched types
25+
}
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs:24:37
3+
|
4+
LL | let _low = self.lows.remove(low.identify()).unwrap();
5+
| ------ ^^^^^^^^^^^^^^ expected `&I`, found associated type
6+
| |
7+
| arguments to this method are incorrect
8+
|
9+
= note: expected reference `&I`
10+
found associated type `<impl LowT as Identify>::Id`
11+
= help: consider constraining the associated type `<impl LowT as Identify>::Id` to `&I`
12+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
13+
note: method defined here
14+
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)