Parse alternative incorrect uses of await and recover
This commit is contained in:
parent
1962adea6a
commit
d763faf921
12 changed files with 428 additions and 37 deletions
|
@ -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)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue