Skip to content

Commit eb1e120

Browse files
committed
fix bug regarding relevant parameters
1 parent 82b7a35 commit eb1e120

File tree

6 files changed

+91
-23
lines changed

6 files changed

+91
-23
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2057,6 +2057,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20572057
// We only really care about the `Self` type itself, which we extract from the ref.
20582058
let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
20592059

2060+
let impl_predicates: ty::GenericPredicates<'tcx> =
2061+
self.tcx.predicates_of(obligation.impl_def_id);
2062+
let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
2063+
// We don't have the index, so we can only guess.
2064+
// TODO: We could conservatively assume that all generics are relevant and go from there instead...
2065+
return Err(expr);
2066+
};
2067+
2068+
if impl_predicate_index >= impl_predicates.predicates.len() {
2069+
// This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
2070+
return Err(expr);
2071+
}
2072+
let relevant_broken_predicate: ty::PredicateKind<'tcx> =
2073+
impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
2074+
2075+
// We want to find which of the generics in the `impl_generics` are relevant to
2076+
// the broken obligation predicate.
2077+
// A generic is relevant if it is mentioned in the "original" predicate. If we can't narrow it down, treat them all as relevant.
2078+
// BUG: Oops, I am looking at the wrong thing here. We should find the original predicate, NOT the self type.
2079+
// This requires adding the impl_predicate_index to the obligation when it is created. TODO: do that.
2080+
let relevant_impl_generics = impl_generics.params.iter();
2081+
2082+
let relevant_impl_generics: Vec<&ty::GenericParamDef> = match relevant_broken_predicate {
2083+
ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => relevant_impl_generics
2084+
.filter(|&generic| {
2085+
// Only retain generics that are mentioned in the (Self type) of this predicate:
2086+
find_param_def_in_ty_walker(broken_trait.trait_ref.self_ty().walk(), generic)
2087+
})
2088+
.collect(),
2089+
_ => {
2090+
relevant_impl_generics.collect() // Treat all generics as potentially relevant
2091+
}
2092+
};
2093+
20602094
// We can only handle Adt types for now.
20612095
// TODO: We could support blanket impls here as well.
20622096
// TODO: We could support tuple impls here as well.
@@ -2068,17 +2102,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20682102
return Err(expr);
20692103
};
20702104

2071-
// We want to find which of the generics in the `impl_generics` are relevant to
2072-
// the broken obligation predicate.
2073-
// A generic is relevant if it is mentioned in the "original" predicate.
2074-
// BUG: Oops, I am looking at the wrong thing here. We should find the original predicate, NOT the self type.
2075-
// This requires adding the impl_predicate_index to the obligation when it is created. TODO: do that.
2076-
let relevant_impl_generics: Vec<&ty::GenericParamDef> = impl_generics
2077-
.params
2078-
.iter()
2079-
.filter(|param| find_param_def_in_ty_walker(impl_self_ty.walk(), param))
2080-
.collect();
2081-
20822105
// We need to find which of the type's arguments are relevant to this obligation.
20832106
// For example, if we had an impl for `SomeTime<(A, C), B, Result<B, C>>` and the broken obligation
20842107
// was `B: Display` then we'd care about indexes `vec![1, 2]`, but if it was `C: PartialEq` then we'd
@@ -2287,7 +2310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22872310
// We failed to find a matching field in the original struct expression.
22882311
Err(expr)
22892312
}
2290-
call_ctor_func_kind => Err(expr),
2313+
_ => Err(expr),
22912314
},
22922315
_ => Err(expr),
22932316
}

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ pub enum WellFormedLoc {
467467
pub struct ImplDerivedObligationCause<'tcx> {
468468
pub derived: DerivedObligationCause<'tcx>,
469469
pub impl_def_id: DefId,
470+
pub impl_def_predicate_index: Option<usize>, // This is only used for diagnostics. It is the index of the predicate.
470471
pub span: Span,
471472
}
472473

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12261226
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
12271227
derived,
12281228
impl_def_id,
1229+
impl_def_predicate_index: None,
12291230
span: obligation.cause.span,
12301231
}))
12311232
});

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,12 +2556,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
25562556
debug!(?predicates);
25572557
assert_eq!(predicates.0.parent, None);
25582558
let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
2559-
for (predicate, span) in predicates.0.predicates {
2559+
for (impl_def_predicate_index, (predicate, span)) in
2560+
predicates.0.predicates.into_iter().enumerate()
2561+
{
25602562
let span = *span;
25612563
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
25622564
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
25632565
derived,
25642566
impl_def_id: def_id,
2567+
impl_def_predicate_index: Some(impl_def_predicate_index),
25652568
span,
25662569
}))
25672570
});
@@ -2862,7 +2865,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
28622865
}
28632866

28642867
fn depth(&self) -> usize {
2865-
if let Some(head) = self.head { head.depth } else { 0 }
2868+
if let Some(head) = self.head {
2869+
head.depth
2870+
} else {
2871+
0
2872+
}
28662873
}
28672874
}
28682875

src/test/ui/tuple/blame-trait-error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ enum TacoKinds<H> {
3636
}
3737
impl<F: T3> T2 for TacoKinds<F> {}
3838

39+
struct GenericBurrito<Spiciness, Filling> {
40+
spiciness: Spiciness,
41+
filling: Filling,
42+
}
43+
impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
44+
struct NotSpicy;
45+
3946
fn want<V: T1>(_x: V) {}
4047

4148
fn example<Q>(q: Q) {
@@ -50,6 +57,9 @@ fn example<Q>(q: Q) {
5057

5158
want(Wrapper { value: TacoKinds::OneTaco(false, q) });
5259
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
60+
61+
want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
62+
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
5363
}
5464

5565
fn main() {}

src/test/ui/tuple/blame-trait-error.stderr

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `Q: T3` is not satisfied
2-
--> $DIR/blame-trait-error.rs:42:60
2+
--> $DIR/blame-trait-error.rs:49:60
33
|
44
LL | want(Wrapper { value: Burrito { spicy: false, filling: q } });
55
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -15,7 +15,7 @@ note: required for `Wrapper<Burrito<Q>>` to implement `T1`
1515
LL | impl<B: T2> T1 for Wrapper<B> {}
1616
| ^^ ^^^^^^^^^^
1717
note: required by a bound in `want`
18-
--> $DIR/blame-trait-error.rs:39:12
18+
--> $DIR/blame-trait-error.rs:46:12
1919
|
2020
LL | fn want<V: T1>(_x: V) {}
2121
| ^^ required by this bound in `want`
@@ -25,7 +25,7 @@ LL | fn example<Q: T3>(q: Q) {
2525
| ++++
2626

2727
error[E0277]: the trait bound `Q: T3` is not satisfied
28-
--> $DIR/blame-trait-error.rs:45:84
28+
--> $DIR/blame-trait-error.rs:52:84
2929
|
3030
LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
3131
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -41,7 +41,7 @@ note: required for `Wrapper<BurritoKinds<Q>>` to implement `T1`
4141
LL | impl<B: T2> T1 for Wrapper<B> {}
4242
| ^^ ^^^^^^^^^^
4343
note: required by a bound in `want`
44-
--> $DIR/blame-trait-error.rs:39:12
44+
--> $DIR/blame-trait-error.rs:46:12
4545
|
4646
LL | fn want<V: T1>(_x: V) {}
4747
| ^^ required by this bound in `want`
@@ -51,7 +51,7 @@ LL | fn example<Q: T3>(q: Q) {
5151
| ++++
5252

5353
error[E0277]: the trait bound `Q: T3` is not satisfied
54-
--> $DIR/blame-trait-error.rs:48:39
54+
--> $DIR/blame-trait-error.rs:55:39
5555
|
5656
LL | want(Wrapper { value: Taco(false, q) });
5757
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -69,7 +69,7 @@ note: required for `Wrapper<Taco<Q>>` to implement `T1`
6969
LL | impl<B: T2> T1 for Wrapper<B> {}
7070
| ^^ ^^^^^^^^^^
7171
note: required by a bound in `want`
72-
--> $DIR/blame-trait-error.rs:39:12
72+
--> $DIR/blame-trait-error.rs:46:12
7373
|
7474
LL | fn want<V: T1>(_x: V) {}
7575
| ^^ required by this bound in `want`
@@ -79,7 +79,7 @@ LL | fn example<Q: T3>(q: Q) {
7979
| ++++
8080

8181
error[E0277]: the trait bound `Q: T3` is not satisfied
82-
--> $DIR/blame-trait-error.rs:51:53
82+
--> $DIR/blame-trait-error.rs:58:53
8383
|
8484
LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
8585
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -97,7 +97,7 @@ note: required for `Wrapper<TacoKinds<Q>>` to implement `T1`
9797
LL | impl<B: T2> T1 for Wrapper<B> {}
9898
| ^^ ^^^^^^^^^^
9999
note: required by a bound in `want`
100-
--> $DIR/blame-trait-error.rs:39:12
100+
--> $DIR/blame-trait-error.rs:46:12
101101
|
102102
LL | fn want<V: T1>(_x: V) {}
103103
| ^^ required by this bound in `want`
@@ -106,6 +106,32 @@ help: consider restricting type parameter `Q`
106106
LL | fn example<Q: T3>(q: Q) {
107107
| ++++
108108

109-
error: aborting due to 4 previous errors
109+
error[E0277]: the trait bound `Q: T3` is not satisfied
110+
--> $DIR/blame-trait-error.rs:61:74
111+
|
112+
LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
113+
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
114+
|
115+
note: required for `GenericBurrito<NotSpicy, Q>` to implement `T2`
116+
--> $DIR/blame-trait-error.rs:43:16
117+
|
118+
LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
119+
| ^^ ^^^^^^^^^^^^^^^^^^^^
120+
note: required for `Wrapper<GenericBurrito<NotSpicy, Q>>` to implement `T1`
121+
--> $DIR/blame-trait-error.rs:12:13
122+
|
123+
LL | impl<B: T2> T1 for Wrapper<B> {}
124+
| ^^ ^^^^^^^^^^
125+
note: required by a bound in `want`
126+
--> $DIR/blame-trait-error.rs:46:12
127+
|
128+
LL | fn want<V: T1>(_x: V) {}
129+
| ^^ required by this bound in `want`
130+
help: consider restricting type parameter `Q`
131+
|
132+
LL | fn example<Q: T3>(q: Q) {
133+
| ++++
134+
135+
error: aborting due to 5 previous errors
110136

111137
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)