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;
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)))
+ }
}
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)?;
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(
}
/// 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;
--> $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
--> $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
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