Don't match any projection predicates when the obligation has inference types or consts in GAT substs
This commit is contained in:
parent
c5e414843e
commit
3602e0e262
4 changed files with 64 additions and 2 deletions
|
@ -2470,8 +2470,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
let projection_ty = ty::ProjectionTy {
|
||||
// `T`
|
||||
substs: self.tcx.mk_substs_trait(
|
||||
trait_pred.self_ty().skip_binder(),
|
||||
self.fresh_substs_for_item(span, item_def_id),
|
||||
trait_ref.self_ty().skip_binder(),
|
||||
&self.fresh_substs_for_item(span, item_def_id)[1..],
|
||||
),
|
||||
// `Future::Output`
|
||||
item_def_id,
|
||||
|
|
|
@ -1521,6 +1521,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
infer_predicate.projection_ty
|
||||
};
|
||||
|
||||
// If the obligation contains any inference types or consts in associated
|
||||
// type substs, then we don't match any projection candidates against it.
|
||||
// This isn't really correct, but otherwise we can end up in a case where
|
||||
// we constrain inference variables by selecting a single predicate, when
|
||||
// we need to stay general. See issue #91762.
|
||||
let (_, predicate_own_substs) =
|
||||
obligation.predicate.trait_ref_and_own_substs(self.infcx.tcx);
|
||||
if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) {
|
||||
return false;
|
||||
}
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation.predicate, infer_projection)
|
||||
|
|
30
src/test/ui/generic-associated-types/issue-91762.rs
Normal file
30
src/test/ui/generic-associated-types/issue-91762.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
// check-fail
|
||||
|
||||
// FIXME(generic_associated_types): We almost certaintly want this to pass, but
|
||||
// it's particularly difficult currently, because we need a way of specifying
|
||||
// that `<Self::Base as Functor>::With<T> = Self` without using that when we have
|
||||
// a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky)
|
||||
// solution. This might be better to just wait for Chalk.
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
pub trait Functor {
|
||||
type With<T>;
|
||||
|
||||
fn fmap<T, U>(this: Self::With<T>) -> Self::With<U>;
|
||||
}
|
||||
|
||||
pub trait FunctorExt<T>: Sized {
|
||||
type Base: Functor<With<T> = Self>;
|
||||
|
||||
fn fmap<U>(self) {
|
||||
let arg: <Self::Base as Functor>::With<T>;
|
||||
let ret: <Self::Base as Functor>::With<U>;
|
||||
|
||||
arg = self;
|
||||
ret = <Self::Base as Functor>::fmap(arg);
|
||||
//~^ mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
22
src/test/ui/generic-associated-types/issue-91762.stderr
Normal file
22
src/test/ui/generic-associated-types/issue-91762.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-91762.rs:25:45
|
||||
|
|
||||
LL | / pub trait FunctorExt<T>: Sized {
|
||||
LL | | type Base: Functor<With<T> = Self>;
|
||||
LL | |
|
||||
LL | | fn fmap<U>(self) {
|
||||
... |
|
||||
LL | | ret = <Self::Base as Functor>::fmap(arg);
|
||||
| | ^^^ expected associated type, found type parameter `Self`
|
||||
LL | |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_- this type parameter
|
||||
|
|
||||
= note: expected associated type `<<Self as FunctorExt<T>>::Base as Functor>::With<_>`
|
||||
found type parameter `Self`
|
||||
= note: you might be missing a type parameter or trait bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue