Skip to content

Commit 3c3e372

Browse files
committed
Auto merge of #54000 - jkozlowski:fix-53174, r=cramertj
Allow named lifetimes in async functions. - Fixes #53174 Code by @eddyb; @cramertj suggested I lift it off another change so we can fix #53174. r? @cramertj
2 parents 5953454 + 4b7f2eb commit 3c3e372

File tree

2 files changed

+89
-21
lines changed

2 files changed

+89
-21
lines changed

src/librustc/hir/map/def_collector.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,38 @@ impl<'a> DefCollector<'a> {
7676
fn visit_async_fn(
7777
&mut self,
7878
id: NodeId,
79-
async_node_id: NodeId,
80-
return_impl_trait_id: NodeId,
8179
name: Name,
8280
span: Span,
83-
visit_fn: impl FnOnce(&mut DefCollector<'a>)
81+
header: &FnHeader,
82+
generics: &'a Generics,
83+
decl: &'a FnDecl,
84+
body: &'a Block,
8485
) {
86+
let (closure_id, return_impl_trait_id) = match header.asyncness {
87+
IsAsync::Async {
88+
closure_id,
89+
return_impl_trait_id,
90+
} => (closure_id, return_impl_trait_id),
91+
_ => unreachable!(),
92+
};
93+
8594
// For async functions, we need to create their inner defs inside of a
8695
// closure to match their desugared representation.
8796
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
8897
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
8998
return self.with_parent(fn_def, |this| {
9099
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
91-
let closure_def = this.create_def(async_node_id,
100+
101+
visit::walk_generics(this, generics);
102+
visit::walk_fn_decl(this, decl);
103+
104+
let closure_def = this.create_def(closure_id,
92105
DefPathData::ClosureExpr,
93106
REGULAR_SPACE,
94107
span);
95-
this.with_parent(closure_def, visit_fn)
108+
this.with_parent(closure_def, |this| {
109+
visit::walk_block(this, body);
110+
})
96111
})
97112
}
98113

@@ -122,17 +137,20 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
122137
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
123138
return visit::walk_item(self, i);
124139
}
125-
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
126-
closure_id,
127-
return_impl_trait_id,
128-
}, .. }, ..) => {
140+
ItemKind::Fn(
141+
ref decl,
142+
ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
143+
ref generics,
144+
ref body,
145+
) => {
129146
return self.visit_async_fn(
130147
i.id,
131-
closure_id,
132-
return_impl_trait_id,
133148
i.ident.name,
134149
i.span,
135-
|this| visit::walk_item(this, i)
150+
header,
151+
generics,
152+
decl,
153+
body,
136154
)
137155
}
138156
ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()),
@@ -233,18 +251,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
233251
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
234252
let def_data = match ii.node {
235253
ImplItemKind::Method(MethodSig {
236-
header: FnHeader { asyncness: IsAsync::Async {
237-
closure_id,
238-
return_impl_trait_id,
239-
}, .. }, ..
240-
}, ..) => {
254+
header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
255+
ref decl,
256+
}, ref body) => {
241257
return self.visit_async_fn(
242258
ii.id,
243-
closure_id,
244-
return_impl_trait_id,
245259
ii.ident.name,
246260
ii.span,
247-
|this| visit::walk_impl_item(this, ii)
261+
header,
262+
&ii.generics,
263+
decl,
264+
body,
248265
)
249266
}
250267
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>

src/test/run-pass/async-await.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ fn async_block(x: u8) -> impl Future<Output = u8> {
6767
}
6868
}
6969

70+
fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
71+
async move {
72+
await!(wake_and_yield_once());
73+
*x
74+
}
75+
}
76+
7077
fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
7178
async move {
7279
let future = async {
@@ -94,6 +101,23 @@ async fn async_fn_with_borrow(x: &u8) -> u8 {
94101
*x
95102
}
96103

104+
async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 {
105+
await!(wake_and_yield_once());
106+
*x
107+
}
108+
109+
fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
110+
async move {
111+
await!(wake_and_yield_once());
112+
*x
113+
}
114+
}
115+
116+
async fn async_fn_with_named_lifetime_multiple_args<'a>(x: &'a u8, _y: &'a u8) -> u8 {
117+
await!(wake_and_yield_once());
118+
*x
119+
}
120+
97121
fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
98122
async move {
99123
await!(async_fn_with_borrow(&y))
@@ -138,16 +162,43 @@ where
138162

139163
fn main() {
140164
macro_rules! test {
141-
($($fn_name:ident,)*) => { $(
165+
($($fn_name:expr,)*) => { $(
142166
test_future_yields_once_then_returns($fn_name);
143167
)* }
144168
}
145169

170+
macro_rules! test_with_borrow {
171+
($($fn_name:expr,)*) => { $(
172+
test_future_yields_once_then_returns(|x| {
173+
async move {
174+
await!($fn_name(&x))
175+
}
176+
});
177+
)* }
178+
}
179+
146180
test! {
147181
async_block,
148182
async_nonmove_block,
149183
async_closure,
150184
async_fn,
151185
async_fn_with_internal_borrow,
186+
|x| {
187+
async move {
188+
unsafe { await!(unsafe_async_fn(x)) }
189+
}
190+
},
191+
}
192+
193+
test_with_borrow! {
194+
async_block_with_borrow_named_lifetime,
195+
async_fn_with_borrow,
196+
async_fn_with_borrow_named_lifetime,
197+
async_fn_with_impl_future_named_lifetime,
198+
|x| {
199+
async move {
200+
await!(async_fn_with_named_lifetime_multiple_args(x, x))
201+
}
202+
},
152203
}
153204
}

0 commit comments

Comments
 (0)