Async methods

This commit is contained in:
Taylor Cramer 2018-06-18 21:18:10 -07:00
parent d02631d3df
commit d64e577fa3
8 changed files with 122 additions and 79 deletions

View file

@ -2932,7 +2932,7 @@ impl<'a> LoweringContext<'a> {
AnonymousLifetimeMode::PassThrough,
|this| {
hir::TraitItemKind::Method(
this.lower_method_sig(sig, trait_item_def_id, false),
this.lower_method_sig(sig, trait_item_def_id, false, false),
hir::TraitMethod::Required(names),
)
},
@ -2950,7 +2950,7 @@ impl<'a> LoweringContext<'a> {
AnonymousLifetimeMode::PassThrough,
|this| {
hir::TraitItemKind::Method(
this.lower_method_sig(sig, trait_item_def_id, false),
this.lower_method_sig(sig, trait_item_def_id, false, false),
hir::TraitMethod::Provided(body_id),
)
},
@ -3021,8 +3021,18 @@ impl<'a> LoweringContext<'a> {
}
ImplItemKind::Method(ref sig, ref body) => {
let body_id = self.lower_body(Some(&sig.decl), |this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
if let IsAsync::Async(async_node_id) = sig.header.asyncness {
let async_expr = this.make_async_expr(
CaptureBy::Value, async_node_id, None,
|this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
});
this.expr(body.span, async_expr, ThinVec::new())
} else {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
}
});
let impl_trait_return_allow = !self.is_in_trait_impl;
@ -3036,6 +3046,7 @@ impl<'a> LoweringContext<'a> {
sig,
impl_item_def_id,
impl_trait_return_allow,
sig.header.asyncness.is_async(),
),
body_id,
)
@ -3201,10 +3212,11 @@ impl<'a> LoweringContext<'a> {
sig: &MethodSig,
fn_def_id: DefId,
impl_trait_return_allow: bool,
is_async: bool,
) -> hir::MethodSig {
hir::MethodSig {
header: self.lower_fn_header(sig.header),
decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, false),
decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async),
}
}

View file

@ -73,6 +73,27 @@ impl<'a> DefCollector<'a> {
self.parent_def = parent;
}
fn visit_async_fn(
&mut self,
id: NodeId,
async_node_id: NodeId,
name: Name,
span: Span,
visit_fn: impl FnOnce(&mut DefCollector<'a>)
) {
// For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation.
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
return self.with_parent(fn_def, |this| {
let closure_def = this.create_def(async_node_id,
DefPathData::ClosureExpr,
REGULAR_SPACE,
span);
this.with_parent(closure_def, visit_fn)
})
}
fn visit_macro_invoc(&mut self, id: NodeId) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData {
@ -100,19 +121,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
return visit::walk_item(self, i);
}
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => {
// For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation.
let fn_def_data = DefPathData::ValueNs(i.ident.name.as_interned_str());
let fn_def = self.create_def(i.id, fn_def_data, ITEM_LIKE_SPACE, i.span);
return self.with_parent(fn_def, |this| {
let closure_def = this.create_def(async_node_id,
DefPathData::ClosureExpr,
REGULAR_SPACE,
i.span);
this.with_parent(closure_def, |this| {
visit::walk_item(this, i);
})
});
return self.visit_async_fn(
i.id,
async_node_id,
i.ident.name,
i.span,
|this| visit::walk_item(this, i)
)
}
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
@ -212,6 +227,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.node {
ImplItemKind::Method(MethodSig {
header: FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..
}, ..) => {
return self.visit_async_fn(
ii.id,
async_node_id,
ii.ident.name,
ii.span,
|this| visit::walk_impl_item(this, ii)
)
}
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_interned_str()),
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),