diff options
| author | David Wood <david@davidtw.co> | 2019-03-12 17:00:20 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2019-04-21 16:46:32 +0100 |
| commit | 879abb1641d97be798010f52a875b9fc83881323 (patch) | |
| tree | 795d9bd80cf7f29b8f52244386aabcc1240adb61 /src/libsyntax/parse/parser.rs | |
| parent | 41c6bb1096abb026d496c2136bb18c001eca46fe (diff) | |
| download | rust-879abb1641d97be798010f52a875b9fc83881323.tar.gz rust-879abb1641d97be798010f52a875b9fc83881323.zip | |
Add `AsyncArgument` to AST.
This commit adds an `AsyncArgument` struct to the AST that contains the generated argument and statement that will be used in HIR lowering, name resolution and def collection.
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8620627765f..26ede5a1057 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,4 +1,4 @@ -use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; +use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy}; use crate::ast::{GenericBound, TraitBoundModifier}; use crate::ast::Unsafety; use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind}; @@ -1517,6 +1517,7 @@ impl<'a> Parser<'a> { IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, + arguments: Vec::new(), } } else { IsAsync::NotAsync @@ -1575,7 +1576,7 @@ impl<'a> Parser<'a> { // trait item macro. (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1589,6 +1590,7 @@ impl<'a> Parser<'a> { p.parse_arg_general(p.span.rust_2018(), true, false) })?; generics.where_clause = self.parse_where_clause()?; + self.construct_async_arguments(&mut asyncness, &d); let sig = ast::MethodSig { header: FnHeader { @@ -6567,7 +6569,7 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn(&mut self, unsafety: Unsafety, - asyncness: Spanned<IsAsync>, + mut asyncness: Spanned<IsAsync>, constness: Spanned<Constness>, abi: Abi) -> PResult<'a, ItemInfo> { @@ -6576,6 +6578,7 @@ impl<'a> Parser<'a> { let decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + self.construct_async_arguments(&mut asyncness, &decl); let header = FnHeader { unsafety, asyncness, constness, abi }; Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) } @@ -6751,11 +6754,12 @@ impl<'a> Parser<'a> { Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; + let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; generics.where_clause = self.parse_where_clause()?; + self.construct_async_arguments(&mut asyncness, &decl); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let header = ast::FnHeader { abi, unsafety, constness, asyncness }; @@ -8177,6 +8181,7 @@ impl<'a> Parser<'a> { respan(async_span, IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, + arguments: Vec::new(), }), respan(fn_span, Constness::NotConst), Abi::Rust)?; @@ -8822,6 +8827,66 @@ impl<'a> Parser<'a> { } } } + + /// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function + /// into the generated closure so that they are dropped when the future is polled and not when + /// it is created. + /// + /// The arguments of the function are replaced in HIR lowering with the arguments created by + /// this function and the statements created here are inserted at the top of the closure body. + fn construct_async_arguments(&mut self, asyncness: &mut Spanned<IsAsync>, decl: &FnDecl) { + if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { + for (index, input) in decl.inputs.iter().enumerate() { + let id = ast::DUMMY_NODE_ID; + let span = input.pat.span; + + // Construct a name for our temporary argument. + let name = format!("__arg{}", index); + let ident = Ident::from_str(&name); + + // Construct an argument representing `__argN: <ty>` to replace the argument of the + // async function. + let arg = Arg { + ty: input.ty.clone(), + id, + pat: P(Pat { + id, + node: PatKind::Ident( + BindingMode::ByValue(Mutability::Immutable), ident, None, + ), + span, + }), + }; + + // Construct a `let <pat>: <ty> = __argN;` statement to insert at the top of the + // async closure. + let local = P(Local { + pat: input.pat.clone(), + ty: Some(P(Ty { + id, + node: input.ty.node.clone(), + span: input.ty.span, + })), + init: Some(P(Expr { + id, + node: ExprKind::Path(None, ast::Path { + span, + segments: vec![PathSegment { ident, id, args: None }], + }), + span, + attrs: ThinVec::new(), + })), + id, + span, + attrs: ThinVec::new(), + source: LocalSource::AsyncFn, + }); + let stmt = Stmt { id, node: StmtKind::Local(local), span, }; + + arguments.push(AsyncArgument { ident, arg, stmt }); + } + } + } } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) { |
