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
This commit is contained in:
commit
3c3e372e18
2 changed files with 89 additions and 21 deletions
|
@ -76,23 +76,38 @@ impl<'a> DefCollector<'a> {
|
||||||
fn visit_async_fn(
|
fn visit_async_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
async_node_id: NodeId,
|
|
||||||
return_impl_trait_id: NodeId,
|
|
||||||
name: Name,
|
name: Name,
|
||||||
span: Span,
|
span: Span,
|
||||||
visit_fn: impl FnOnce(&mut DefCollector<'a>)
|
header: &FnHeader,
|
||||||
|
generics: &'a Generics,
|
||||||
|
decl: &'a FnDecl,
|
||||||
|
body: &'a Block,
|
||||||
) {
|
) {
|
||||||
|
let (closure_id, return_impl_trait_id) = match header.asyncness {
|
||||||
|
IsAsync::Async {
|
||||||
|
closure_id,
|
||||||
|
return_impl_trait_id,
|
||||||
|
} => (closure_id, return_impl_trait_id),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
// For async functions, we need to create their inner defs inside of a
|
// For async functions, we need to create their inner defs inside of a
|
||||||
// closure to match their desugared representation.
|
// closure to match their desugared representation.
|
||||||
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
|
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
|
||||||
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
|
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
|
||||||
return self.with_parent(fn_def, |this| {
|
return self.with_parent(fn_def, |this| {
|
||||||
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
|
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
|
||||||
let closure_def = this.create_def(async_node_id,
|
|
||||||
|
visit::walk_generics(this, generics);
|
||||||
|
visit::walk_fn_decl(this, decl);
|
||||||
|
|
||||||
|
let closure_def = this.create_def(closure_id,
|
||||||
DefPathData::ClosureExpr,
|
DefPathData::ClosureExpr,
|
||||||
REGULAR_SPACE,
|
REGULAR_SPACE,
|
||||||
span);
|
span);
|
||||||
this.with_parent(closure_def, visit_fn)
|
this.with_parent(closure_def, |this| {
|
||||||
|
visit::walk_block(this, body);
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,17 +137,20 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
|
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
|
||||||
return visit::walk_item(self, i);
|
return visit::walk_item(self, i);
|
||||||
}
|
}
|
||||||
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
|
ItemKind::Fn(
|
||||||
closure_id,
|
ref decl,
|
||||||
return_impl_trait_id,
|
ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
|
||||||
}, .. }, ..) => {
|
ref generics,
|
||||||
|
ref body,
|
||||||
|
) => {
|
||||||
return self.visit_async_fn(
|
return self.visit_async_fn(
|
||||||
i.id,
|
i.id,
|
||||||
closure_id,
|
|
||||||
return_impl_trait_id,
|
|
||||||
i.ident.name,
|
i.ident.name,
|
||||||
i.span,
|
i.span,
|
||||||
|this| visit::walk_item(this, i)
|
header,
|
||||||
|
generics,
|
||||||
|
decl,
|
||||||
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()),
|
ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()),
|
||||||
|
@ -233,18 +251,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||||
let def_data = match ii.node {
|
let def_data = match ii.node {
|
||||||
ImplItemKind::Method(MethodSig {
|
ImplItemKind::Method(MethodSig {
|
||||||
header: FnHeader { asyncness: IsAsync::Async {
|
header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
|
||||||
closure_id,
|
ref decl,
|
||||||
return_impl_trait_id,
|
}, ref body) => {
|
||||||
}, .. }, ..
|
|
||||||
}, ..) => {
|
|
||||||
return self.visit_async_fn(
|
return self.visit_async_fn(
|
||||||
ii.id,
|
ii.id,
|
||||||
closure_id,
|
|
||||||
return_impl_trait_id,
|
|
||||||
ii.ident.name,
|
ii.ident.name,
|
||||||
ii.span,
|
ii.span,
|
||||||
|this| visit::walk_impl_item(this, ii)
|
header,
|
||||||
|
&ii.generics,
|
||||||
|
decl,
|
||||||
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
|
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
|
||||||
|
|
|
@ -67,6 +67,13 @@ fn async_block(x: u8) -> impl Future<Output = u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
|
||||||
|
async move {
|
||||||
|
await!(wake_and_yield_once());
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
|
fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
|
||||||
async move {
|
async move {
|
||||||
let future = async {
|
let future = async {
|
||||||
|
@ -94,6 +101,23 @@ async fn async_fn_with_borrow(x: &u8) -> u8 {
|
||||||
*x
|
*x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 {
|
||||||
|
await!(wake_and_yield_once());
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a {
|
||||||
|
async move {
|
||||||
|
await!(wake_and_yield_once());
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_fn_with_named_lifetime_multiple_args<'a>(x: &'a u8, _y: &'a u8) -> u8 {
|
||||||
|
await!(wake_and_yield_once());
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
|
||||||
fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
|
fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
|
||||||
async move {
|
async move {
|
||||||
await!(async_fn_with_borrow(&y))
|
await!(async_fn_with_borrow(&y))
|
||||||
|
@ -138,16 +162,43 @@ where
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
macro_rules! test {
|
macro_rules! test {
|
||||||
($($fn_name:ident,)*) => { $(
|
($($fn_name:expr,)*) => { $(
|
||||||
test_future_yields_once_then_returns($fn_name);
|
test_future_yields_once_then_returns($fn_name);
|
||||||
)* }
|
)* }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! test_with_borrow {
|
||||||
|
($($fn_name:expr,)*) => { $(
|
||||||
|
test_future_yields_once_then_returns(|x| {
|
||||||
|
async move {
|
||||||
|
await!($fn_name(&x))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
)* }
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
async_block,
|
async_block,
|
||||||
async_nonmove_block,
|
async_nonmove_block,
|
||||||
async_closure,
|
async_closure,
|
||||||
async_fn,
|
async_fn,
|
||||||
async_fn_with_internal_borrow,
|
async_fn_with_internal_borrow,
|
||||||
|
|x| {
|
||||||
|
async move {
|
||||||
|
unsafe { await!(unsafe_async_fn(x)) }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
test_with_borrow! {
|
||||||
|
async_block_with_borrow_named_lifetime,
|
||||||
|
async_fn_with_borrow,
|
||||||
|
async_fn_with_borrow_named_lifetime,
|
||||||
|
async_fn_with_impl_future_named_lifetime,
|
||||||
|
|x| {
|
||||||
|
async move {
|
||||||
|
await!(async_fn_with_named_lifetime_multiple_args(x, x))
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue