skip checking supertraits in assembly_object_bound_candidate for NormalizesTo goal

This commit is contained in:
Adwin White 2025-11-21 11:54:27 +08:00
parent fb505a7985
commit 525cdc75dc
3 changed files with 55 additions and 0 deletions

View file

@ -74,6 +74,8 @@ where
/// Consider a clause specifically for a `dyn Trait` self type. This requires
/// additionally checking all of the supertraits and object bounds to hold,
/// since they're not implied by the well-formedness of the object type.
/// `NormalizesTo` overrides this to not check the supertraits for backwards
/// compatibility with the old solver. cc trait-system-refactor-initiative#245.
fn probe_and_consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, D>,
source: CandidateSource<I>,

View file

@ -184,6 +184,20 @@ where
then(ecx)
}
// Hack for trait-system-refactor-initiative#245.
// FIXME(-Zhigher-ranked-assumptions): this impl differs from trait goals and we should unify
// them again once we properly support binders.
fn probe_and_consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, D>,
source: CandidateSource<I>,
goal: Goal<I, Self>,
assumption: I::Clause,
) -> Result<Candidate<I>, NoSolution> {
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
fn consider_additional_alias_assumptions(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,

View file

@ -0,0 +1,39 @@
//@ check-pass
//@ compile-flags: -Znext-solver
//@ edition: 2024
// A regression test for trait-system-refactor-initiative#245.
// The old solver doesn't check the supertraits of the principal trait
// when considering object candidate for normalization.
// And the new solver previously did, resulting in a placeholder error
// while normalizing inside of a generator witness.
trait AsyncFn: Send + 'static {
type Fut: Future<Output = ()> + Send;
fn call(&self) -> Self::Fut;
}
type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
fn wrap_call<P: AsyncFn + ?Sized>(func: Box<P>) -> impl Future<Output = ()> {
func.call()
}
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
todo!()
}
async fn cursed_fut() {
wrap_call(get_boxed_fn()).await;
}
fn observe_fut_not_send() {
fn assert_send<T: Send>(t: T) -> T {
t
}
assert_send(cursed_fut());
}
fn main() {}