Skip to content

Commit 19dcbd1

Browse files
committed
Explicitly gather lifetimes and definitions for bare async fns
1 parent 25825cd commit 19dcbd1

File tree

1 file changed

+30
-39
lines changed
  • compiler/rustc_ast_lowering/src

1 file changed

+30
-39
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -751,31 +751,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
751751
})
752752
}
753753

754-
/// Setup lifetime capture for and impl-trait.
755-
/// The captures will be added to `captures`.
756-
fn while_capturing_lifetimes<T>(
757-
&mut self,
758-
parent_def_id: LocalDefId,
759-
captures: &mut FxHashMap<LocalDefId, (Span, NodeId, ParamName, LifetimeRes)>,
760-
f: impl FnOnce(&mut Self) -> T,
761-
) -> T {
762-
let lifetime_stash = std::mem::replace(
763-
&mut self.captured_lifetimes,
764-
Some(LifetimeCaptureContext {
765-
parent_def_id,
766-
captures: std::mem::take(captures),
767-
binders_to_ignore: Default::default(),
768-
}),
769-
);
770-
771-
let ret = f(self);
772-
773-
let ctxt = std::mem::replace(&mut self.captured_lifetimes, lifetime_stash).unwrap();
774-
*captures = ctxt.captures;
775-
776-
ret
777-
}
778-
779754
/// Register a binder to be ignored for lifetime capture.
780755
#[tracing::instrument(level = "debug", skip(self, f))]
781756
#[inline]
@@ -1786,20 +1761,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17861761
debug!(?captures);
17871762

17881763
self.with_hir_id_owner(opaque_ty_node_id, |this| {
1789-
let future_bound =
1790-
this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| {
1791-
// We have to be careful to get elision right here. The
1792-
// idea is that we create a lifetime parameter for each
1793-
// lifetime in the return type. So, given a return type
1794-
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
1795-
// Future<Output = &'1 [ &'2 u32 ]>`.
1796-
//
1797-
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
1798-
// hence the elision takes place at the fn site.
1799-
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
1800-
});
1801-
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
1802-
debug!("lower_async_fn_ret_ty: captures={:#?}", captures);
1764+
let lifetime_stash = std::mem::replace(
1765+
&mut this.captured_lifetimes,
1766+
Some(LifetimeCaptureContext {
1767+
parent_def_id: opaque_ty_def_id,
1768+
captures: std::mem::take(&mut captures),
1769+
binders_to_ignore: Default::default(),
1770+
}),
1771+
);
1772+
1773+
let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_ret_ty(output);
1774+
debug!(?lifetimes_in_bounds);
1775+
debug!(?binders_to_ignore);
1776+
1777+
this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore);
1778+
1779+
// We have to be careful to get elision right here. The
1780+
// idea is that we create a lifetime parameter for each
1781+
// lifetime in the return type. So, given a return type
1782+
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
1783+
// Future<Output = &'1 [ &'2 u32 ]>`.
1784+
//
1785+
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
1786+
// hence the elision takes place at the fn site.
1787+
let ret = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
1788+
1789+
let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap();
1790+
1791+
captures = ctxt.captures;
1792+
1793+
let future_bound = ret;
18031794

18041795
let generic_params =
18051796
this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| {

0 commit comments

Comments
 (0)