Rollup merge of #139828 - compiler-errors:rigid-trait, r=lcnr

Don't require rigid alias's trait to hold

See test for write-up. TL;DR is that we don't need the trait bound to hold, since we enforce it during WF.

I think this is preferable to introducing (if we even could do so) a more specific hack around coroutine interiors, higher ranked types, etc, since this is just a manifestation of more pervasive issues w/ lifetime erasure in coroutines. This just doesn't manifest in the old solver b/c it doesn't try to prove `T: Trait` holds when rigidly projecting `<T as Trait>::Assoc`.

It's pretty clear that this affects quite a few traits (https://github.com/rust-lang/rust/pull/139763), so I think this needs fixing.

r? lcnr

Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/177
This commit is contained in:
Matthias Krüger 2025-04-17 00:16:22 +02:00 committed by GitHub
commit c594a88f43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

View file

@ -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)
})
})

View file

@ -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() {}