about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorTaylor Cramer <cramertj@google.com>2019-04-18 12:55:23 -0700
committerTaylor Cramer <cramertj@google.com>2019-05-07 14:45:53 -0700
commitfe8760cb848d45f5c83b41e689878b893b74e45d (patch)
tree8042688119098da68322461411aa8c44cfdcb3d4 /src/libsyntax
parentc3b8ab5199af4a3c11d14b0cbdb17a641e8eee71 (diff)
downloadrust-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.rs13
-rw-r--r--src/libsyntax/feature_gate.rs18
-rw-r--r--src/libsyntax/mut_visit.rs1
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/libsyntax/parse/token.rs5
-rw-r--r--src/libsyntax/print/pprust.rs12
-rw-r--r--src/libsyntax/util/parser.rs3
-rw-r--r--src/libsyntax/visit.rs1
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);