about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJack Huey <31162821+jackh726@users.noreply.github.com>2022-01-14 20:51:30 -0500
committerJack Huey <31162821+jackh726@users.noreply.github.com>2022-02-07 14:54:40 -0500
commit3602e0e262275c898966c45553c406c4873472fe (patch)
treed5c160e725fc0fa6c1e52cbb49209ab63847aeb3
parentc5e414843ebfe25674d8e18a5369d6249fdee741 (diff)
downloadrust-3602e0e262275c898966c45553c406c4873472fe.tar.gz
rust-3602e0e262275c898966c45553c406c4873472fe.zip
Don't match any projection predicates when the obligation has inference types or consts in GAT substs
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs10
-rw-r--r--src/test/ui/generic-associated-types/issue-91762.rs30
-rw-r--r--src/test/ui/generic-associated-types/issue-91762.stderr22
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`.