diff options
| author | Jack Huey <31162821+jackh726@users.noreply.github.com> | 2022-01-14 20:51:30 -0500 |
|---|---|---|
| committer | Jack Huey <31162821+jackh726@users.noreply.github.com> | 2022-02-07 14:54:40 -0500 |
| commit | 3602e0e262275c898966c45553c406c4873472fe (patch) | |
| tree | d5c160e725fc0fa6c1e52cbb49209ab63847aeb3 | |
| parent | c5e414843ebfe25674d8e18a5369d6249fdee741 (diff) | |
| download | rust-3602e0e262275c898966c45553c406c4873472fe.tar.gz rust-3602e0e262275c898966c45553c406c4873472fe.zip | |
Don't match any projection predicates when the obligation has inference types or consts in GAT substs
4 files changed, 64 insertions, 2 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6634f3e364d..9a7d06ef640 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 47427395b93..562535b0fea 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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) diff --git a/src/test/ui/generic-associated-types/issue-91762.rs b/src/test/ui/generic-associated-types/issue-91762.rs new file mode 100644 index 00000000000..e39a127abfd --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.rs @@ -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() {} diff --git a/src/test/ui/generic-associated-types/issue-91762.stderr b/src/test/ui/generic-associated-types/issue-91762.stderr new file mode 100644 index 00000000000..e177e151d8a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-91762.stderr @@ -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`. |
