Skip to content

Commit b9d6fe3

Browse files
committed
Review comments
- Change wording of suggestion - Move recovery logic to `diagnostics.rs` - Reduce ammount of code duplication
1 parent 0183a57 commit b9d6fe3

File tree

3 files changed

+81
-109
lines changed

3 files changed

+81
-109
lines changed

src/libsyntax/parse/diagnostics.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::ast;
2-
use crate::ast::{Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
2+
use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
33
use crate::parse::parser::PathStyle;
44
use crate::parse::token;
55
use crate::parse::PResult;
@@ -223,4 +223,42 @@ impl<'a> Parser<'a> {
223223
false
224224
}
225225
}
226+
227+
/// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
228+
/// and `await { <expr> }`.
229+
crate fn parse_incorrect_await_syntax(
230+
&mut self,
231+
lo: Span,
232+
await_sp: Span,
233+
) -> PResult<'a, (Span, ExprKind)> {
234+
let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
235+
let expr = if self.token == token::OpenDelim(token::Brace) {
236+
// Handle `await { <expr> }`.
237+
// This needs to be handled separatedly from the next arm to avoid
238+
// interpreting `await { <expr> }?` as `<expr>?.await`.
239+
self.parse_block_expr(
240+
None,
241+
self.span,
242+
BlockCheckMode::Default,
243+
ThinVec::new(),
244+
)
245+
} else {
246+
self.parse_expr()
247+
}.map_err(|mut err| {
248+
err.span_label(await_sp, "while parsing this incorrect await expression");
249+
err
250+
})?;
251+
let expr_str = self.sess.source_map().span_to_snippet(expr.span)
252+
.unwrap_or_else(|_| pprust::expr_to_string(&expr));
253+
let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
254+
let sp = lo.to(expr.span);
255+
let app = match expr.node {
256+
ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
257+
_ => Applicability::MachineApplicable,
258+
};
259+
self.struct_span_err(sp, "incorrect use of `await`")
260+
.span_suggestion(sp, "`await` is a postfix operation", suggestion, app)
261+
.emit();
262+
Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr)))
263+
}
226264
}

src/libsyntax/parse/parser.rs

Lines changed: 29 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,10 +2629,9 @@ impl<'a> Parser<'a> {
26292629
db.note("variable declaration using `let` is a statement");
26302630
return Err(db);
26312631
} else if self.span.rust_2018() && self.eat_keyword(keywords::Await) {
2632-
let await_sp = self.prev_span;
2633-
let e = self.parse_async_macro_or_stmt(lo, await_sp)?;
2634-
hi = e.0;
2635-
ex = e.1;
2632+
let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?;
2633+
hi = await_hi;
2634+
ex = e_kind;
26362635
} else if self.token.is_path_start() {
26372636
let path = self.parse_path(PathStyle::Expr)?;
26382637

@@ -2697,97 +2696,29 @@ impl<'a> Parser<'a> {
26972696
self.maybe_recover_from_bad_qpath(expr, true)
26982697
}
26992698

2700-
fn parse_async_macro_or_stmt(
2699+
/// Parse `await!(<expr>)` calls, or alternatively recover from incorrect but reasonable
2700+
/// alternative syntaxes `await <expr>`, `await? <expr>`, `await(<expr>)` and
2701+
/// `await { <expr> }`.
2702+
fn parse_await_macro_or_alt(
27012703
&mut self,
27022704
lo: Span,
27032705
await_sp: Span,
27042706
) -> PResult<'a, (Span, ExprKind)> {
2705-
Ok(match self.token {
2706-
token::Not => {
2707-
// Handle correct `await!(<expr>)`
2708-
// FIXME: make this an error when `await!` is no longer supported
2709-
// https://github.com/rust-lang/rust/issues/60610
2710-
self.expect(&token::Not)?;
2711-
self.expect(&token::OpenDelim(token::Paren))?;
2712-
let expr = self.parse_expr().map_err(|mut err| {
2713-
err.span_label(
2714-
await_sp,
2715-
"while parsing this await macro call",
2716-
);
2717-
err
2718-
})?;
2719-
self.expect(&token::CloseDelim(token::Paren))?;
2720-
(expr.span, ExprKind::Await(ast::AwaitOrigin::MacroLike, expr))
2721-
}
2722-
token::Question => {
2723-
// Handle `await? <expr>`
2724-
self.bump(); // `?`
2725-
let expr = self.parse_expr().map_err(|mut err| {
2726-
err.span_label(
2727-
await_sp,
2728-
"while parsing this incorrect await statement",
2729-
);
2730-
err
2731-
})?;
2732-
let sp = lo.to(expr.span);
2733-
let expr_str = self.sess.source_map().span_to_snippet(expr.span)
2734-
.unwrap_or_else(|_| pprust::expr_to_string(&expr));
2735-
let expr = self.mk_expr(
2736-
sp,
2737-
ExprKind::Await(ast::AwaitOrigin::FieldLike, expr),
2738-
ThinVec::new(),
2739-
);
2740-
let mut err = self.struct_span_err(
2741-
sp,
2742-
"incorrect use of `await`",
2743-
);
2744-
err.span_suggestion(
2745-
sp,
2746-
"`await` is not a statement",
2747-
format!("{}.await?", expr_str),
2748-
Applicability::MachineApplicable,
2749-
);
2750-
err.emit();
2751-
(sp, ExprKind::Try(expr))
2752-
}
2753-
ref t => {
2754-
// Handle `await <expr>`
2755-
let expr = if t == &token::OpenDelim(token::Brace) {
2756-
// Handle `await { <expr> }`
2757-
// this needs to be handled separatedly from the next arm to avoid
2758-
// interpreting `await { <expr> }?` as `<expr>?.await`
2759-
self.parse_block_expr(
2760-
None,
2761-
self.span,
2762-
BlockCheckMode::Default,
2763-
ThinVec::new(),
2764-
)
2765-
} else {
2766-
self.parse_expr()
2767-
}.map_err(|mut err| {
2768-
err.span_label(
2769-
await_sp,
2770-
"while parsing this incorrect await statement",
2771-
);
2772-
err
2773-
})?;
2774-
let expr_str = self.sess.source_map().span_to_snippet(expr.span)
2775-
.unwrap_or_else(|_| pprust::expr_to_string(&expr));
2776-
let sp = lo.to(expr.span);
2777-
let mut err = self.struct_span_err(
2778-
sp,
2779-
"incorrect use of `await`",
2780-
);
2781-
err.span_suggestion(
2782-
sp,
2783-
"`await` is not a statement",
2784-
format!("{}.await", expr_str),
2785-
Applicability::MachineApplicable,
2786-
);
2787-
err.emit();
2788-
(sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr))
2789-
}
2790-
})
2707+
if self.token == token::Not {
2708+
// Handle correct `await!(<expr>)`.
2709+
// FIXME: make this an error when `await!` is no longer supported
2710+
// https://github.com/rust-lang/rust/issues/60610
2711+
self.expect(&token::Not)?;
2712+
self.expect(&token::OpenDelim(token::Paren))?;
2713+
let expr = self.parse_expr().map_err(|mut err| {
2714+
err.span_label(await_sp, "while parsing this await macro call");
2715+
err
2716+
})?;
2717+
self.expect(&token::CloseDelim(token::Paren))?;
2718+
Ok((expr.span, ExprKind::Await(ast::AwaitOrigin::MacroLike, expr)))
2719+
} else { // Handle `await <expr>`.
2720+
self.parse_incorrect_await_syntax(lo, await_sp)
2721+
}
27912722
}
27922723

27932724
fn maybe_parse_struct_expr(
@@ -2938,10 +2869,13 @@ impl<'a> Parser<'a> {
29382869
}
29392870

29402871
/// Parses a block or unsafe block.
2941-
fn parse_block_expr(&mut self, opt_label: Option<Label>,
2942-
lo: Span, blk_mode: BlockCheckMode,
2943-
outer_attrs: ThinVec<Attribute>)
2944-
-> PResult<'a, P<Expr>> {
2872+
crate fn parse_block_expr(
2873+
&mut self,
2874+
opt_label: Option<Label>,
2875+
lo: Span,
2876+
blk_mode: BlockCheckMode,
2877+
outer_attrs: ThinVec<Attribute>,
2878+
) -> PResult<'a, P<Expr>> {
29452879
self.expect(&token::OpenDelim(token::Brace))?;
29462880

29472881
let mut attrs = outer_attrs;

src/test/ui/await-keyword/incorrect-syntax-suggestions.stderr

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,43 @@ error: incorrect use of `await`
22
--> $DIR/incorrect-syntax-suggestions.rs:10:13
33
|
44
LL | let _ = await bar();
5-
| ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
5+
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
66

77
error: incorrect use of `await`
88
--> $DIR/incorrect-syntax-suggestions.rs:14:13
99
|
1010
LL | let _ = await? bar();
11-
| ^^^^^^^^^^^^ help: `await` is not a statement: `bar().await?`
11+
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
1212

1313
error: incorrect use of `await`
1414
--> $DIR/incorrect-syntax-suggestions.rs:18:13
1515
|
1616
LL | let _ = await bar()?;
17-
| ^^^^^^^^^^^^ help: `await` is not a statement: `bar()?.await`
17+
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
1818

1919
error: incorrect use of `await`
2020
--> $DIR/incorrect-syntax-suggestions.rs:23:13
2121
|
2222
LL | let _ = await { bar() };
23-
| ^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ bar() }.await`
23+
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
2424

2525
error: incorrect use of `await`
2626
--> $DIR/incorrect-syntax-suggestions.rs:27:13
2727
|
2828
LL | let _ = await(bar());
29-
| ^^^^^^^^^^^^ help: `await` is not a statement: `(bar()).await`
29+
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
3030

3131
error: incorrect use of `await`
3232
--> $DIR/incorrect-syntax-suggestions.rs:31:13
3333
|
3434
LL | let _ = await { bar() }?;
35-
| ^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ bar() }.await`
35+
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
3636

3737
error: incorrect use of `await`
3838
--> $DIR/incorrect-syntax-suggestions.rs:35:14
3939
|
4040
LL | let _ = (await bar())?;
41-
| ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
41+
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
4242

4343
error: incorrect use of `await`
4444
--> $DIR/incorrect-syntax-suggestions.rs:39:24
@@ -56,25 +56,25 @@ error: incorrect use of `await`
5656
--> $DIR/incorrect-syntax-suggestions.rs:55:13
5757
|
5858
LL | let _ = await bar();
59-
| ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
59+
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
6060

6161
error: incorrect use of `await`
6262
--> $DIR/incorrect-syntax-suggestions.rs:60:13
6363
|
6464
LL | let _ = await? bar();
65-
| ^^^^^^^^^^^^ help: `await` is not a statement: `bar().await?`
65+
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
6666

6767
error: incorrect use of `await`
6868
--> $DIR/incorrect-syntax-suggestions.rs:65:13
6969
|
7070
LL | let _ = await bar()?;
71-
| ^^^^^^^^^^^^ help: `await` is not a statement: `bar()?.await`
71+
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
7272

7373
error: incorrect use of `await`
7474
--> $DIR/incorrect-syntax-suggestions.rs:70:14
7575
|
7676
LL | let _ = (await bar())?;
77-
| ^^^^^^^^^^^ help: `await` is not a statement: `bar().await`
77+
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
7878

7979
error: incorrect use of `await`
8080
--> $DIR/incorrect-syntax-suggestions.rs:75:24
@@ -94,13 +94,13 @@ error: expected expression, found `=>`
9494
LL | match await { await => () }
9595
| ----- ^^ expected expression
9696
| |
97-
| while parsing this incorrect await statement
97+
| while parsing this incorrect await expression
9898

9999
error: incorrect use of `await`
100100
--> $DIR/incorrect-syntax-suggestions.rs:108:11
101101
|
102102
LL | match await { await => () }
103-
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is not a statement: `{ await => () }.await`
103+
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
104104

105105
error: expected one of `.`, `?`, `{`, or an operator, found `}`
106106
--> $DIR/incorrect-syntax-suggestions.rs:111:1

0 commit comments

Comments
 (0)