]> git.lizzy.rs Git - rust.git/commitdiff
Review comments
authorEsteban Küber <esteban@kuber.com.ar>
Thu, 16 May 2019 20:33:26 +0000 (13:33 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Thu, 16 May 2019 20:58:44 +0000 (13:58 -0700)
- Change wording of suggestion
- Move recovery logic to `diagnostics.rs`
- Reduce ammount of code duplication

src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/parser.rs
src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr

index 32e1ee94f0dfb702f8ce3667b888e73a95c322d7..61453e35095bebd8085af45c78a6455b239d7720 100644 (file)
@@ -1,5 +1,5 @@
 use crate::ast;
-use crate::ast::{Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
+use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
 use crate::parse::parser::PathStyle;
 use crate::parse::token;
 use crate::parse::PResult;
@@ -223,4 +223,42 @@ impl<'a> Parser<'a> {
             false
         }
     }
+
+    /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
+    /// and `await { <expr> }`.
+    crate fn parse_incorrect_await_syntax(
+        &mut self,
+        lo: Span,
+        await_sp: Span,
+    ) -> PResult<'a, (Span, ExprKind)> {
+        let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
+        let expr = if self.token == 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 expression");
+            err
+        })?;
+        let expr_str = self.sess.source_map().span_to_snippet(expr.span)
+            .unwrap_or_else(|_| pprust::expr_to_string(&expr));
+        let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
+        let sp = lo.to(expr.span);
+        let app = match expr.node {
+            ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
+            _ => Applicability::MachineApplicable,
+        };
+        self.struct_span_err(sp, "incorrect use of `await`")
+            .span_suggestion(sp, "`await` is a postfix operation", suggestion, app)
+            .emit();
+        Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr)))
+    }
 }
index 45081aadfd97b64073fd6d73e450f0497dcdb90d..bb0f9fa9502a0ccacb890b173c95e5d4023e5b98 100644 (file)
@@ -2629,10 +2629,9 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     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 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
         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 @@ fn parse_or_use_outer_attributes(&mut self,
     }
 
     /// 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;
index bc7bd77479e40986e6ded969bd5d100e9ccdfea5..380da4448ad323ee0a2853215a212de245aaac21 100644 (file)
@@ -2,43 +2,43 @@ error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:10:13
    |
 LL |     let _ = await bar();
-   |             ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
+   |             ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:14:13
    |
 LL |     let _ = await? bar();
-   |             ^^^^^^^^^^^^ help: `await` is not a statement: `bar().await?`
+   |             ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:18:13
    |
 LL |     let _ = await bar()?;
-   |             ^^^^^^^^^^^^ help: `await` is not a statement: `bar()?.await`
+   |             ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:23:13
    |
 LL |     let _ = await { bar() };
-   |             ^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ bar() }.await`
+   |             ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:27:13
    |
 LL |     let _ = await(bar());
-   |             ^^^^^^^^^^^^ help: `await` is not a statement: `(bar()).await`
+   |             ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:31:13
    |
 LL |     let _ = await { bar() }?;
-   |             ^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ bar() }.await`
+   |             ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:35:14
    |
 LL |     let _ = (await bar())?;
-   |              ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
+   |              ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:39:24
@@ -56,25 +56,25 @@ error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:55:13
    |
 LL |     let _ = await bar();
-   |             ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
+   |             ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:60:13
    |
 LL |     let _ = await? bar();
-   |             ^^^^^^^^^^^^ help: `await` is not a statement: `bar().await?`
+   |             ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:65:13
    |
 LL |     let _ = await bar()?;
-   |             ^^^^^^^^^^^^ help: `await` is not a statement: `bar()?.await`
+   |             ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:70:14
    |
 LL |     let _ = (await bar())?;
-   |              ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
+   |              ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:75:24
@@ -94,13 +94,13 @@ error: expected expression, found `=>`
 LL |     match await { await => () }
    |                   ----- ^^ expected expression
    |                   |
-   |                   while parsing this incorrect await statement
+   |                   while parsing this incorrect await expression
 
 error: incorrect use of `await`
   --> $DIR/incorrect-syntax-suggestions.rs:108:11
    |
 LL |     match await { await => () }
-   |           ^^^^^^^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ await => () }.await`
+   |           ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
 
 error: expected one of `.`, `?`, `{`, or an operator, found `}`
   --> $DIR/incorrect-syntax-suggestions.rs:111:1