Explicitly gather lifetimes and definitions for bare async fns

This commit is contained in:
Santiago Pastorino 2022-07-26 15:11:15 -03:00
parent 25825cd4fa
commit 19dcbd151b
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF

View file

@ -751,31 +751,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
}
/// Setup lifetime capture for and impl-trait.
/// The captures will be added to `captures`.
fn while_capturing_lifetimes<T>(
&mut self,
parent_def_id: LocalDefId,
captures: &mut FxHashMap<LocalDefId, (Span, NodeId, ParamName, LifetimeRes)>,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let lifetime_stash = std::mem::replace(
&mut self.captured_lifetimes,
Some(LifetimeCaptureContext {
parent_def_id,
captures: std::mem::take(captures),
binders_to_ignore: Default::default(),
}),
);
let ret = f(self);
let ctxt = std::mem::replace(&mut self.captured_lifetimes, lifetime_stash).unwrap();
*captures = ctxt.captures;
ret
}
/// Register a binder to be ignored for lifetime capture.
#[tracing::instrument(level = "debug", skip(self, f))]
#[inline]
@ -1786,8 +1761,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug!(?captures);
self.with_hir_id_owner(opaque_ty_node_id, |this| {
let future_bound =
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
let lifetime_stash = std::mem::replace(
&mut this.captured_lifetimes,
Some(LifetimeCaptureContext {
parent_def_id: opaque_ty_def_id,
captures: std::mem::take(&mut captures),
binders_to_ignore: Default::default(),
}),
);
let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_ret_ty(output);
debug!(?lifetimes_in_bounds);
debug!(?binders_to_ignore);
this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore);
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
@ -1796,10 +1784,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
//
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
// hence the elision takes place at the fn site.
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
});
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
debug!("lower_async_fn_ret_ty: captures={:#?}", captures);
let ret = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap();
captures = ctxt.captures;
let future_bound = ret;
let generic_params =
this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| {