diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-05-15 19:47:18 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-05-16 13:56:44 -0700 |
| commit | d763faf92198e3f0c851388c71d2bb8a2f04afd9 (patch) | |
| tree | 2613a847c021be3e35e5c78480b24be0249ff770 /src/libsyntax/parse/parser.rs | |
| parent | 1962adea6ad9b992516ae56ad7f8c5bc33b951cb (diff) | |
| download | rust-d763faf92198e3f0c851388c71d2bb8a2f04afd9.tar.gz rust-d763faf92198e3f0c851388c71d2bb8a2f04afd9.zip | |
Parse alternative incorrect uses of await and recover
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 113 |
1 files changed, 105 insertions, 8 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99e8db9d8e6..55e13ef00dc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2629,14 +2629,94 @@ 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) { - // 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))?; - hi = self.prev_span; - ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr); + let await_sp = self.prev_span; + match self.token { + token::Not => { + // 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))?; + ex = 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(), + ); + hi = sp; + ex = ExprKind::Try(expr); + let mut err = self.struct_span_err( + await_sp, + "incorrect use of `await`", + ); + err.span_suggestion( + sp, + "`await` is not a statement", + format!("{}.await?", expr_str), + Applicability::MachineApplicable, + ); + err.emit(); + } + 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); + hi = sp; + ex = ExprKind::Await(ast::AwaitOrigin::FieldLike, expr); + let mut err = self.struct_span_err( + await_sp, + "incorrect use of `await`", + ); + err.span_suggestion( + sp, + "`await` is not a statement", + format!("{}.await", expr_str), + Applicability::MachineApplicable, + ); + err.emit(); + } + } } else if self.token.is_path_start() { let path = self.parse_path(PathStyle::Expr)?; @@ -2913,6 +2993,23 @@ impl<'a> Parser<'a> { ExprKind::Await(ast::AwaitOrigin::FieldLike, self_arg), ThinVec::new(), ); + if self.token == token::OpenDelim(token::Paren) && + self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) + { + // future.await() + let lo = self.span; + self.bump(); // ( + let sp = lo.to(self.span); + self.bump(); // ) + let mut err = self.struct_span_err(span, "incorrect use of `await`"); + err.span_suggestion( + sp, + "`await` is not a method call, remove the parentheses", + String::new(), + Applicability::MachineApplicable, + ); + err.emit() + } return Ok(await_expr); } let segment = self.parse_path_segment(PathStyle::Expr)?; |
