about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-04-16 18:30:33 +0000
committerMichael Goulet <michael@errs.io>2025-04-16 20:06:39 +0000
commitbb3c98165cca752ba93927f19fa3f78c48caccc7 (patch)
tree3acc71df3f13f92e1d20296fd161ab3c0a19c8f1
parentafa859f8121bf2985362a2c8414dc71a825ccf2d (diff)
downloadrust-bb3c98165cca752ba93927f19fa3f78c48caccc7.tar.gz
rust-bb3c98165cca752ba93927f19fa3f78c48caccc7.zip
Don't require rigid alias's trait to hold
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs1
-rw-r--r--tests/ui/coroutine/higher-ranked-rigid.rs41
2 files changed, 41 insertions, 1 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 2d027f16e5d..fdeb276a58e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -45,7 +45,6 @@ where
                             goal,
                             goal.predicate.alias,
                         );
-                        this.add_goal(GoalSource::AliasWellFormed, goal.with(cx, trait_ref));
                         this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                     })
                 })
diff --git a/tests/ui/coroutine/higher-ranked-rigid.rs b/tests/ui/coroutine/higher-ranked-rigid.rs
new file mode 100644
index 00000000000..23a7d51300c
--- /dev/null
+++ b/tests/ui/coroutine/higher-ranked-rigid.rs
@@ -0,0 +1,41 @@
+//@ edition: 2024
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/177>.
+// Coroutines erase all free lifetimes from their interior types, replacing them with higher-
+// ranked regions which act as universals, to properly represent the fact that we don't know what
+// the value of the region is within the coroutine.
+//
+// In the future in `from_request`, that means that the `'r` lifetime is being replaced in
+// `<T as FromRequest<'r>>::Assoc`, which is in present in the existential bounds of the
+// `dyn Future` that it's awaiting. Normalizing this associated type, with its free lifetimes
+// replaced, means proving `T: FromRequest<'!0>`, which doesn't hold without constraining the
+// `'!0` lifetime, which we don't do today.
+
+// Proving `T: Trait` holds when `<T as Trait>::Assoc` is rigid is not necessary for soundness,
+// at least not *yet*, and it's not even necessary for diagnostics since we have other special
+// casing for, e.g., AliasRelate goals failing in the BestObligation folder.
+
+// The old solver unintentioanlly avoids this by never checking that `T: Trait` holds when
+// `<T as Trait>::Assoc` is rigid. Introducing this additional requirement when projecting rigidly
+// in the old solver causes this (and tons of production crates) to fail. See the fallout from the
+// crater run at <https://github.com/rust-lang/rust/pull/139763>.
+
+use std::future::Future;
+use std::pin::Pin;
+
+pub trait FromRequest<'r> {
+    type Assoc;
+    fn from_request() -> Pin<Box<dyn Future<Output = Self::Assoc> + Send>>;
+}
+
+fn test<'r, T: FromRequest<'r>>() -> Pin<Box<dyn Future<Output = ()> + Send>> {
+    Box::pin(async move {
+        T::from_request().await;
+    })
+}
+
+fn main() {}