about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-02-08 16:40:48 +0100
committerGitHub <noreply@github.com>2022-02-08 16:40:48 +0100
commita11e2b1f755e392e7c776b98e76aa86a30b7b22e (patch)
treeb332e296015c8868de7e32f74c4417dbcee92619
parent8429dcdb79b35182036e8de574287a7acc4b14d8 (diff)
parent7ad48bd4e22aaffa5ac32809b9196fab9c04de2c (diff)
downloadrust-a11e2b1f755e392e7c776b98e76aa86a30b7b22e.tar.gz
rust-a11e2b1f755e392e7c776b98e76aa86a30b7b22e.zip
Rollup merge of #92917 - jackh726:issue-91762-2, r=nikomatsakis
Don't constrain projection predicates with inference vars in GAT substs

cc #91762

Not a fix, but a mitigation to prevent a backwards-compatible hazard where we normalize using a predicate only because it's the only one available, but shouldn't. This would constrain an inference variable which didn't really want. We already do this when selecting a projection candidate, which isn't always correct. But changing that is a problem for a different day.

Also found out that a suggestion for `await`ing a future was using the wrong substs.

r? ``@nikomatsakis``
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs10
-rw-r--r--src/test/ui/generic-associated-types/issue-74824.rs1
-rw-r--r--src/test/ui/generic-associated-types/issue-74824.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-91762.rs30
-rw-r--r--src/test/ui/generic-associated-types/issue-91762.stderr9
6 files changed, 60 insertions, 3 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 51b8c9aca78..65a18897b39 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2473,7 +2473,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     // `T`
                     substs: self.tcx.mk_substs_trait(
                         trait_pred.self_ty().skip_binder(),
-                        self.fresh_substs_for_item(span, item_def_id),
+                        &self.fresh_substs_for_item(span, item_def_id)[1..],
                     ),
                     // `Future::Output`
                     item_def_id,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 5e7d4c8b415..36cc14610cb 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1073,6 +1073,16 @@ fn project<'cx, 'tcx>(
         return Ok(Projected::Progress(Progress::error(selcx.tcx())));
     }
 
+    // If the obligation contains any inference types or consts in associated
+    // type substs, then we don't assemble any candidates.
+    // 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(selcx.tcx());
+    if predicate_own_substs.iter().any(|g| g.has_infer_types_or_consts()) {
+        return Err(ProjectionError::TooManyCandidates);
+    }
+
     let mut candidates = ProjectionCandidateSet::None;
 
     // Make sure that the following procedures are kept in order. ParamEnv
diff --git a/src/test/ui/generic-associated-types/issue-74824.rs b/src/test/ui/generic-associated-types/issue-74824.rs
index 1bbf7aac5cd..01f99fa4487 100644
--- a/src/test/ui/generic-associated-types/issue-74824.rs
+++ b/src/test/ui/generic-associated-types/issue-74824.rs
@@ -17,6 +17,7 @@ impl<T> UnsafeCopy for T {}
 fn main() {
     let b = Box::new(42usize);
     let copy = <()>::copy(&b);
+    //~^ type annotations needed
 
     let raw_b = Box::deref(&b) as *const _;
     let raw_copy = Box::deref(&copy) as *const _;
diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr
index 8517eb9fa21..e7ebf5964ba 100644
--- a/src/test/ui/generic-associated-types/issue-74824.stderr
+++ b/src/test/ui/generic-associated-types/issue-74824.stderr
@@ -27,6 +27,13 @@ help: consider restricting type parameter `T`
 LL |     type Copy<T: std::clone::Clone>: Copy = Box<T>;
    |                +++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error[E0282]: type annotations needed
+  --> $DIR/issue-74824.rs:19:16
+   |
+LL |     let copy = <()>::copy(&b);
+   |                ^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `copy`
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0282.
+For more information about an error, try `rustc --explain E0277`.
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..b259a3c6e06
--- /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);
+        //~^ type annotations needed
+    }
+}
+
+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..a9c465cdd7e
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-91762.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-91762.rs:25:15
+   |
+LL |         ret = <Self::Base as Functor>::fmap(arg);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `fmap`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.