about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-05-16 13:33:26 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-05-16 13:58:44 -0700
commitb9d6fe3ae96a7f1f478dc6baf29b8e4cff5ab865 (patch)
treecacec5fe5fed51d05d3829435284069e6299e38e /src/libsyntax/parse/parser.rs
parent0183a575f686003586ca3308db8a55d6224f4789 (diff)
downloadrust-b9d6fe3ae96a7f1f478dc6baf29b8e4cff5ab865.tar.gz
rust-b9d6fe3ae96a7f1f478dc6baf29b8e4cff5ab865.zip
Review comments
- Change wording of suggestion
- Move recovery logic to `diagnostics.rs`
- Reduce ammount of code duplication
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs124
1 files changed, 29 insertions, 95 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 45081aadfd9..bb0f9fa9502 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2629,10 +2629,9 @@ impl<'a> Parser<'a> {
                     db.note("variable declaration using `let` is a statement");
                     return Err(db);
                 } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) {
-                    let await_sp = self.prev_span;
-                    let e = self.parse_async_macro_or_stmt(lo, await_sp)?;
-                    hi = e.0;
-                    ex = e.1;
+                    let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?;
+                    hi = await_hi;
+                    ex = e_kind;
                 } else if self.token.is_path_start() {
                     let path = self.parse_path(PathStyle::Expr)?;
 
@@ -2697,97 +2696,29 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
-    fn parse_async_macro_or_stmt(
+    /// Parse `await!(<expr>)` calls, or alternatively recover from incorrect but reasonable
+    /// alternative syntaxes `await <expr>`, `await? <expr>`, `await(<expr>)` and
+    /// `await { <expr> }`.
+    fn parse_await_macro_or_alt(
         &mut self,
         lo: Span,
         await_sp: Span,
     ) -> PResult<'a, (Span, ExprKind)> {
-        Ok(match self.token {
-            token::Not => {
-                // Handle correct `await!(<expr>)`
-                // FIXME: make this an error 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().map_err(|mut err| {
-                    err.span_label(
-                        await_sp,
-                        "while parsing this await macro call",
-                    );
-                    err
-                })?;
-                self.expect(&token::CloseDelim(token::Paren))?;
-                (expr.span, ExprKind::Await(ast::AwaitOrigin::MacroLike, expr))
-            }
-            token::Question => {
-                // Handle `await? <expr>`
-                self.bump(); // `?`
-                let expr = self.parse_expr().map_err(|mut err| {
-                    err.span_label(
-                        await_sp,
-                        "while parsing this incorrect await statement",
-                    );
-                    err
-                })?;
-                let sp = lo.to(expr.span);
-                let expr_str = self.sess.source_map().span_to_snippet(expr.span)
-                    .unwrap_or_else(|_| pprust::expr_to_string(&expr));
-                let expr = self.mk_expr(
-                    sp,
-                    ExprKind::Await(ast::AwaitOrigin::FieldLike, expr),
-                    ThinVec::new(),
-                );
-                let mut err = self.struct_span_err(
-                    sp,
-                    "incorrect use of `await`",
-                );
-                err.span_suggestion(
-                    sp,
-                    "`await` is not a statement",
-                    format!("{}.await?", expr_str),
-                    Applicability::MachineApplicable,
-                );
-                err.emit();
-                (sp, ExprKind::Try(expr))
-            }
-            ref t => {
-                // Handle `await <expr>`
-                let expr = if t == &token::OpenDelim(token::Brace) {
-                    // Handle `await { <expr> }`
-                    // this needs to be handled separatedly from the next arm to avoid
-                    // interpreting `await { <expr> }?` as `<expr>?.await`
-                    self.parse_block_expr(
-                        None,
-                        self.span,
-                        BlockCheckMode::Default,
-                        ThinVec::new(),
-                    )
-                } else {
-                    self.parse_expr()
-                }.map_err(|mut err| {
-                    err.span_label(
-                        await_sp,
-                        "while parsing this incorrect await statement",
-                    );
-                    err
-                })?;
-                let expr_str = self.sess.source_map().span_to_snippet(expr.span)
-                    .unwrap_or_else(|_| pprust::expr_to_string(&expr));
-                let sp = lo.to(expr.span);
-                let mut err = self.struct_span_err(
-                    sp,
-                    "incorrect use of `await`",
-                );
-                err.span_suggestion(
-                    sp,
-                    "`await` is not a statement",
-                    format!("{}.await", expr_str),
-                    Applicability::MachineApplicable,
-                );
-                err.emit();
-                (sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr))
-            }
-        })
+        if self.token == token::Not {
+            // Handle correct `await!(<expr>)`.
+            // FIXME: make this an error 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().map_err(|mut err| {
+                err.span_label(await_sp, "while parsing this await macro call");
+                err
+            })?;
+            self.expect(&token::CloseDelim(token::Paren))?;
+            Ok((expr.span, ExprKind::Await(ast::AwaitOrigin::MacroLike, expr)))
+        } else { // Handle `await <expr>`.
+            self.parse_incorrect_await_syntax(lo, await_sp)
+        }
     }
 
     fn maybe_parse_struct_expr(
@@ -2938,10 +2869,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a block or unsafe block.
-    fn parse_block_expr(&mut self, opt_label: Option<Label>,
-                            lo: Span, blk_mode: BlockCheckMode,
-                            outer_attrs: ThinVec<Attribute>)
-                            -> PResult<'a, P<Expr>> {
+    crate fn parse_block_expr(
+        &mut self,
+        opt_label: Option<Label>,
+        lo: Span,
+        blk_mode: BlockCheckMode,
+        outer_attrs: ThinVec<Attribute>,
+    ) -> PResult<'a, P<Expr>> {
         self.expect(&token::OpenDelim(token::Brace))?;
 
         let mut attrs = outer_attrs;