diff options
| author | Taylor Cramer <cramertj@google.com> | 2019-04-18 12:55:23 -0700 |
|---|---|---|
| committer | Taylor Cramer <cramertj@google.com> | 2019-05-07 14:45:53 -0700 |
| commit | fe8760cb848d45f5c83b41e689878b893b74e45d (patch) | |
| tree | 8042688119098da68322461411aa8c44cfdcb3d4 /src/libsyntax | |
| parent | c3b8ab5199af4a3c11d14b0cbdb17a641e8eee71 (diff) | |
| download | rust-fe8760cb848d45f5c83b41e689878b893b74e45d.tar.gz rust-fe8760cb848d45f5c83b41e689878b893b74e45d.zip | |
Implement built-in await syntax
Adds support for .await under the existing async_await feature gate. Moves macro-like await! syntax to the await_macro feature gate. Removes support for `await` as a non-keyword under the `async_await` feature.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/util/parser.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 1 |
8 files changed, 70 insertions, 0 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 33b8c76bb53..af2302d24f5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1065,6 +1065,7 @@ impl Expr { ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, ExprKind::Async(..) => ExprPrecedence::Async, + ExprKind::Await(..) => ExprPrecedence::Await, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, ExprKind::Field(..) => ExprPrecedence::Field, @@ -1186,6 +1187,9 @@ pub enum ExprKind { /// created during lowering cannot be made the parent of any other /// preexisting defs. Async(CaptureBy, NodeId, P<Block>), + /// An await expression (`my_future.await`). + Await(AwaitOrigin, P<Expr>), + /// A try block (`try { ... }`). TryBlock(P<Block>), @@ -1287,6 +1291,15 @@ pub enum Movability { Movable, } +/// Whether an `await` comes from `await!` or `.await` syntax. +/// FIXME: this should be removed when support for legacy `await!` is removed. +/// https://github.com/rust-lang/rust/issues/60610 +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +pub enum AwaitOrigin { + FieldLike, + MacroLike, +} + pub type Mac = Spanned<Mac_>; /// Represents a macro invocation. The `Path` indicates which macro diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2a1f3c48014..dda5ac1f4e1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -485,6 +485,10 @@ declare_features! ( // Allows async and await syntax. (active, async_await, "1.28.0", Some(50547), None), + // Allows await! macro-like syntax. + // This will likely be removed prior to stabilization of async/await. + (active, await_macro, "1.28.0", Some(50547), None), + // Allows reinterpretation of the bits of a value of one type as another type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), @@ -2104,6 +2108,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::Async(..) => { gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); } + ast::ExprKind::Await(origin, _) => { + match origin { + ast::AwaitOrigin::FieldLike => + gate_feature_post!(&self, async_await, e.span, "async/await is unstable"), + ast::AwaitOrigin::MacroLike => + gate_feature_post!( + &self, + await_macro, + e.span, + "`await!(<expr>)` macro syntax is unstable, and will soon be removed \ + in favor of `<expr>.await` syntax." + ), + } + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 2e09235ca77..6eb8b1b5004 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1185,6 +1185,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr, vis.visit_id(node_id); vis.visit_block(body); } + ExprKind::Await(_origin, expr) => vis.visit_expr(expr), ExprKind::Assign(el, er) => { vis.visit_expr(el); vis.visit_expr(er); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d46feeab335..c5d76188565 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2751,6 +2751,14 @@ impl<'a> Parser<'a> { db.span_label(self.span, "expected expression"); db.note("variable declaration using `let` is a statement"); return Err(db); + } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + // FIXME: remove this branch when `await!` is no longer supported + // https://github.com/rust-lang/rust/issues/60610 + self.expect(&token::Not)?; + self.expect(&token::OpenDelim(token::Paren))?; + let expr = self.parse_expr()?; + self.expect(&token::CloseDelim(token::Paren))?; + ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr); } else if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; @@ -3014,6 +3022,15 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { + if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + let span = lo.to(self.prev_span); + let await_expr = self.mk_expr( + span, + ExprKind::Await(ast::AwaitOrigin::FieldLike, self_arg), + ThinVec::new(), + ); + return Ok(await_expr); + } let segment = self.parse_path_segment(PathStyle::Expr)?; self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2fa4f5263fb..fd7a39c576d 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -99,6 +99,11 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { ident_token.is_path_segment_keyword() || [ keywords::Async.name(), + + // FIXME: remove when `await!(..)` syntax is removed + // https://github.com/rust-lang/rust/issues/60610 + keywords::Await.name(), + keywords::Do.name(), keywords::Box.name(), keywords::Break.name(), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6c0fdfaa776..682621d40ab 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2250,6 +2250,18 @@ impl<'a> State<'a> { self.ibox(0)?; self.print_block_with_attrs(blk, attrs)?; } + ast::ExprKind::Await(origin, ref expr) => { + match origin { + ast::AwaitOrigin::MacroLike => { + self.s.word("await!")?; + self.print_expr_maybe_paren(expr, parser::PREC_FORCE_PAREN)?; + } + ast::AwaitOrigin::FieldLike => { + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?; + self.s.word(".await")?; + } + } + } ast::ExprKind::Assign(ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1)?; diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 5f15ede7b0b..80dabffaba9 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -267,6 +267,7 @@ pub enum ExprPrecedence { TryBlock, Struct, Async, + Await, Err, } @@ -301,6 +302,7 @@ impl ExprPrecedence { ExprPrecedence::Unary => PREC_PREFIX, // Unary, postfix + ExprPrecedence::Await | ExprPrecedence::Call | ExprPrecedence::MethodCall | ExprPrecedence::Field | @@ -346,6 +348,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { // X { y: 1 } + X { y: 2 } contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } + ast::ExprKind::Await(_, ref x) | ast::ExprKind::Unary(_, ref x) | ast::ExprKind::Cast(ref x, _) | ast::ExprKind::Type(ref x, _) | diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index fc99d10b0b6..0503e5644db 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -768,6 +768,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Async(_, _, ref body) => { visitor.visit_block(body); } + ExprKind::Await(_, ref expr) => visitor.visit_expr(expr), ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(left_hand_expression); visitor.visit_expr(right_hand_expression); |
