1
Fork 0

Teach typeck/borrowck/solvers how to deal with async closures

This commit is contained in:
Michael Goulet 2024-01-24 22:27:25 +00:00
parent c567eddec2
commit a82bae2172
35 changed files with 1221 additions and 66 deletions

View file

@ -303,6 +303,66 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)])
}
fn consider_builtin_async_fn_trait_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
goal_kind: ty::ClosureKind,
) -> QueryResult<'tcx> {
if goal.predicate.polarity != ty::ImplPolarity::Positive {
return Err(NoSolution);
}
let tcx = ecx.tcx();
let (tupled_inputs_and_output_and_coroutine, nested_preds) =
structural_traits::extract_tupled_inputs_and_output_from_async_callable(
tcx,
goal.predicate.self_ty(),
goal_kind,
// This region doesn't matter because we're throwing away the coroutine type
tcx.lifetimes.re_static,
)?;
let output_is_sized_pred =
tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| {
ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
});
let pred = tupled_inputs_and_output_and_coroutine
.map_bound(|(inputs, _, _)| {
ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
})
.to_predicate(tcx);
// A built-in `AsyncFn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
Self::consider_implied_clause(
ecx,
goal,
pred,
[goal.with(tcx, output_is_sized_pred)]
.into_iter()
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
)
}
fn consider_builtin_async_fn_kind_helper_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
bug!();
};
let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
// We don't need to worry about the self type being an infer var.
return Err(NoSolution);
};
let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
if closure_kind.extends(goal_kind) {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
Err(NoSolution)
}
}
fn consider_builtin_tuple_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,