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

@ -746,15 +746,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
function_kind: FnKind<'tcx>,
declaration: &'tcx FnDecl,
_: Span,
node_id: NodeId) {
let rib_kind = match function_kind {
FnKind::ItemFn(..) => {
ItemRibKind
}
FnKind::Method(_, _, _, _) => {
TraitOrImplItemRibKind
}
FnKind::Closure(_) => ClosureRibKind(node_id),
node_id: NodeId)
{
let (rib_kind, asyncness) = match function_kind {
FnKind::ItemFn(_, ref header, ..) =>
(ItemRibKind, header.asyncness),
FnKind::Method(_, ref sig, _, _) =>
(TraitOrImplItemRibKind, sig.header.asyncness),
FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
(ClosureRibKind(node_id), IsAsync::NotAsync),
};
// Create a value rib for the function.
@ -774,7 +776,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
}
visit::walk_fn_ret_ty(self, &declaration.output);
// Resolve the function body.
// Resolve the function body, potentially inside the body of an async closure
if let IsAsync::Async(async_closure_id) = asyncness {
let rib_kind = ClosureRibKind(async_closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
self.label_ribs.push(Rib::new(rib_kind));
}
match function_kind {
FnKind::ItemFn(.., body) |
FnKind::Method(.., body) => {
@ -785,6 +793,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
}
};
// Leave the body of the async closure
if asyncness.is_async() {
self.label_ribs.pop();
self.ribs[ValueNS].pop();
}
debug!("(resolving function) leaving function");
self.label_ribs.pop();
@ -2054,47 +2068,6 @@ impl<'a> Resolver<'a> {
self.check_proc_macro_attrs(&item.attrs);
match item.node {
ItemKind::Fn(ref declaration,
FnHeader { asyncness: IsAsync::Async(async_closure_id), .. },
ref generics,
ref body) => {
// Async functions are desugared from `async fn foo() { .. }`
// to `fn foo() { future_from_generator(move || ... ) }`,
// so we have to visit the body inside the closure scope
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
this.visit_vis(&item.vis);
this.visit_ident(item.ident);
this.visit_generics(generics);
let rib_kind = ItemRibKind;
this.ribs[ValueNS].push(Rib::new(rib_kind));
this.label_ribs.push(Rib::new(rib_kind));
let mut bindings_list = FxHashMap();
for argument in &declaration.inputs {
this.resolve_pattern(
&argument.pat, PatternSource::FnParam, &mut bindings_list);
this.visit_ty(&*argument.ty);
}
visit::walk_fn_ret_ty(this, &declaration.output);
// Now resolve the inner closure
{
let rib_kind = ClosureRibKind(async_closure_id);
this.ribs[ValueNS].push(Rib::new(rib_kind));
this.label_ribs.push(Rib::new(rib_kind));
// No need to resolve either arguments nor return type,
// as this closure has neither
// Resolve the body
this.visit_block(body);
this.label_ribs.pop();
this.ribs[ValueNS].pop();
}
this.label_ribs.pop();
this.ribs[ValueNS].pop();
walk_list!(this, visit_attribute, &item.attrs);
})
}
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
ItemKind::Struct(_, ref generics) |
@ -2415,7 +2388,7 @@ impl<'a> Resolver<'a> {
visit::walk_impl_item(this, impl_item)
);
}
ImplItemKind::Method(_, _) => {
ImplItemKind::Method(..) => {
// If this is a trait impl, ensure the method
// exists in trait
this.check_trait_item(impl_item.ident,