More comments, final tweaks
This commit is contained in:
parent
37184e86ea
commit
c98d6994a3
20 changed files with 169 additions and 42 deletions
|
@ -309,14 +309,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
|||
}
|
||||
|
||||
// Returns a binder of the tupled inputs types, output type, and coroutine type
|
||||
// from a builtin async closure type.
|
||||
// from a builtin coroutine-closure type. If we don't yet know the closure kind of
|
||||
// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
|
||||
// which enforces the closure is actually callable with the given trait. When we
|
||||
// know the kind already, we can short-circuit this check.
|
||||
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
goal_kind: ty::ClosureKind,
|
||||
env_region: ty::Region<'tcx>,
|
||||
) -> Result<(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Vec<ty::Predicate<'tcx>>), NoSolution>
|
||||
{
|
||||
) -> Result<
|
||||
(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Option<ty::Predicate<'tcx>>),
|
||||
NoSolution,
|
||||
> {
|
||||
match *self_ty.kind() {
|
||||
ty::CoroutineClosure(def_id, args) => {
|
||||
let args = args.as_coroutine_closure();
|
||||
|
@ -339,7 +344,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
|||
);
|
||||
(sig.tupled_inputs_ty, sig.return_ty, coroutine_ty)
|
||||
}),
|
||||
vec![],
|
||||
None,
|
||||
))
|
||||
} else {
|
||||
let async_fn_kind_trait_def_id =
|
||||
|
@ -350,6 +355,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
|||
.next()
|
||||
.unwrap()
|
||||
.def_id;
|
||||
// When we don't know the closure kind (and therefore also the closure's upvars,
|
||||
// which are computed at the same time), we must delay the computation of the
|
||||
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
||||
// goal functions similarly to the old `ClosureKind` predicate, and ensures that
|
||||
// the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
|
||||
// will project to the right upvars for the generator, appending the inputs and
|
||||
// coroutine upvars respecting the closure kind.
|
||||
Ok((
|
||||
args.coroutine_closure_sig().map_bound(|sig| {
|
||||
let tupled_upvars_ty = Ty::new_projection(
|
||||
|
@ -373,14 +385,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
|||
);
|
||||
(sig.tupled_inputs_ty, sig.return_ty, coroutine_ty)
|
||||
}),
|
||||
vec![
|
||||
Some(
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
async_fn_kind_trait_def_id,
|
||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
],
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2491,6 +2491,9 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
|||
// since all this does is make the solver do more work.
|
||||
//
|
||||
// The code duplication due to the different length args is kind of weird, too.
|
||||
//
|
||||
// See the logic in `structural_traits` in the new solver to understand a bit
|
||||
// more clearly how this *should* look.
|
||||
let poly_cache_entry = args.coroutine_closure_sig().map_bound(|sig| {
|
||||
let (projection_ty, term) = match tcx.item_name(obligation.predicate.def_id) {
|
||||
sym::CallOnceFuture => {
|
||||
|
|
|
@ -121,9 +121,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
|
||||
}
|
||||
|
||||
// FIXME: Put these into `else if` blocks above, since they're built-in.
|
||||
self.assemble_closure_candidates(obligation, &mut candidates);
|
||||
self.assemble_async_closure_candidates(obligation, &mut candidates);
|
||||
self.assemble_fn_pointer_candidates(obligation, &mut candidates);
|
||||
|
||||
self.assemble_candidates_from_impls(obligation, &mut candidates);
|
||||
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
|
||||
}
|
||||
|
@ -382,6 +384,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check that the self kind extends the goal kind. If it does,
|
||||
// then there's nothing else to check.
|
||||
if let Some(closure_kind) = self_ty.to_opt_closure_kind()
|
||||
&& let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
|
||||
{
|
||||
|
|
|
@ -88,6 +88,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
|
||||
}
|
||||
|
||||
// No nested obligations or confirmation process. The checks that we do in
|
||||
// candidate assembly are sufficient.
|
||||
AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]),
|
||||
|
||||
CoroutineCandidate => {
|
||||
|
|
|
@ -728,7 +728,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
}
|
||||
|
||||
ty::CoroutineClosure(did, args) => {
|
||||
// See the above comments.
|
||||
// See the above comments. The same apply to coroutine-closures.
|
||||
walker.skip_current_subtree();
|
||||
self.compute(args.as_coroutine_closure().tupled_upvars_ty().into());
|
||||
let obligations = self.nominal_obligations(did, args);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue