Skip to content

Commit 3602e0e

Browse files
committed
Don't match any projection predicates when the obligation has inference types or consts in GAT substs
1 parent c5e4148 commit 3602e0e

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,8 +2470,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
24702470
let projection_ty = ty::ProjectionTy {
24712471
// `T`
24722472
substs: self.tcx.mk_substs_trait(
2473-
trait_pred.self_ty().skip_binder(),
2474-
self.fresh_substs_for_item(span, item_def_id),
2473+
trait_ref.self_ty().skip_binder(),
2474+
&self.fresh_substs_for_item(span, item_def_id)[1..],
24752475
),
24762476
// `Future::Output`
24772477
item_def_id,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15211521
infer_predicate.projection_ty
15221522
};
15231523

1524+
// If the obligation contains any inference types or consts in associated
1525+
// type substs, then we don't match any projection candidates against it.
1526+
// This isn't really correct, but otherwise we can end up in a case where
1527+
// we constrain inference variables by selecting a single predicate, when
1528+
// we need to stay general. See issue #91762.
1529+
let (_, predicate_own_substs) =
1530+
obligation.predicate.trait_ref_and_own_substs(self.infcx.tcx);
1531+
if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) {
1532+
return false;
1533+
}
15241534
self.infcx
15251535
.at(&obligation.cause, obligation.param_env)
15261536
.sup(obligation.predicate, infer_projection)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// check-fail
2+
3+
// FIXME(generic_associated_types): We almost certaintly want this to pass, but
4+
// it's particularly difficult currently, because we need a way of specifying
5+
// that `<Self::Base as Functor>::With<T> = Self` without using that when we have
6+
// a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky)
7+
// solution. This might be better to just wait for Chalk.
8+
9+
#![feature(generic_associated_types)]
10+
11+
pub trait Functor {
12+
type With<T>;
13+
14+
fn fmap<T, U>(this: Self::With<T>) -> Self::With<U>;
15+
}
16+
17+
pub trait FunctorExt<T>: Sized {
18+
type Base: Functor<With<T> = Self>;
19+
20+
fn fmap<U>(self) {
21+
let arg: <Self::Base as Functor>::With<T>;
22+
let ret: <Self::Base as Functor>::With<U>;
23+
24+
arg = self;
25+
ret = <Self::Base as Functor>::fmap(arg);
26+
//~^ mismatched types
27+
}
28+
}
29+
30+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-91762.rs:25:45
3+
|
4+
LL | / pub trait FunctorExt<T>: Sized {
5+
LL | | type Base: Functor<With<T> = Self>;
6+
LL | |
7+
LL | | fn fmap<U>(self) {
8+
... |
9+
LL | | ret = <Self::Base as Functor>::fmap(arg);
10+
| | ^^^ expected associated type, found type parameter `Self`
11+
LL | |
12+
LL | | }
13+
LL | | }
14+
| |_- this type parameter
15+
|
16+
= note: expected associated type `<<Self as FunctorExt<T>>::Base as Functor>::With<_>`
17+
found type parameter `Self`
18+
= note: you might be missing a type parameter or trait bound
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)