Skip to content

Commit f21c0a2

Browse files
committed
Suggest adding {} for 'label: non_block_expr
1 parent a2da4af commit f21c0a2

File tree

5 files changed

+122
-12
lines changed

5 files changed

+122
-12
lines changed

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ use rustc_ast::tokenstream::Spacing;
1313
use rustc_ast::util::classify;
1414
use rustc_ast::util::literal::LitError;
1515
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
16+
use rustc_ast::StmtKind;
1617
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp, DUMMY_NODE_ID};
1718
use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
1819
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
1920
use rustc_ast_pretty::pprust;
21+
use rustc_data_structures::thin_vec::ThinVec;
2022
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
2123
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
2224
use rustc_session::lint::BuiltinLintDiagnostics;
@@ -1548,9 +1550,33 @@ impl<'a> Parser<'a> {
15481550
Ok(self.mk_expr_err(lo))
15491551
} else {
15501552
let msg = "expected `while`, `for`, `loop` or `{` after a label";
1551-
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
1553+
1554+
let mut err = self.struct_span_err(self.token.span, msg);
1555+
err.span_label(self.token.span, msg);
1556+
15521557
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
1553-
self.parse_expr()
1558+
let expr = self.parse_expr().map(|expr| {
1559+
let span = expr.span;
1560+
let sugg_msg = "consider enclosing expression in a block";
1561+
let suggestions = vec![
1562+
(span.shrink_to_lo(), "{".to_owned()),
1563+
(span.shrink_to_hi(), "}".to_owned()),
1564+
];
1565+
1566+
err.multipart_suggestion_verbose(
1567+
sugg_msg,
1568+
suggestions,
1569+
Applicability::MachineApplicable,
1570+
);
1571+
1572+
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`.
1573+
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
1574+
let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span);
1575+
self.mk_expr(span, ExprKind::Block(blk, label), ThinVec::new())
1576+
});
1577+
1578+
err.emit();
1579+
expr
15541580
}?;
15551581

15561582
if !ate_colon && consume_colon {

src/test/ui/parser/labeled-no-colon-expr.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
4747
|
4848
LL | 'l4 0;
4949
| ^ expected `while`, `for`, `loop` or `{` after a label
50+
|
51+
help: consider enclosing expression in a block
52+
|
53+
LL | 'l4 {0};
54+
| + +
5055

5156
error: labeled expression must be followed by `:`
5257
--> $DIR/labeled-no-colon-expr.rs:8:9
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-rustfix
2+
#![feature(label_break_value)]
3+
fn main() {
4+
#[allow(unused_labels)]
5+
'label: {1 + 1}; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
6+
7+
'label: {match () { () => break 'label, }}; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
8+
9+
let x = 1;
10+
let _i = 'label: {match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
11+
0 => 42,
12+
1 if false => break 'label 17,
13+
1 => {
14+
if true {
15+
break 'label 13
16+
} else {
17+
break 'label 0;
18+
}
19+
}
20+
_ => 1,
21+
}};
22+
23+
let other = 3;
24+
let _val = 'label: {(1, if other == 3 { break 'label (2, 3) } else { other })}; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
25+
}
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
1+
// run-rustfix
2+
#![feature(label_break_value)]
13
fn main() {
4+
#[allow(unused_labels)]
25
'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
36

4-
let _recovery_witness: () = 0; //~ ERROR mismatched types
7+
'label: match () { () => break 'label, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
8+
9+
let x = 1;
10+
let _i = 'label: match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
11+
0 => 42,
12+
1 if false => break 'label 17,
13+
1 => {
14+
if true {
15+
break 'label 13
16+
} else {
17+
break 'label 0;
18+
}
19+
}
20+
_ => 1,
21+
};
22+
23+
let other = 3;
24+
let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); //~ ERROR expected `while`, `for`, `loop` or `{` after a label
525
}

src/test/ui/parser/recover-labeled-non-block-expr.stderr

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,51 @@
11
error: expected `while`, `for`, `loop` or `{` after a label
2-
--> $DIR/recover-labeled-non-block-expr.rs:2:13
2+
--> $DIR/recover-labeled-non-block-expr.rs:5:13
33
|
44
LL | 'label: 1 + 1;
55
| ^ expected `while`, `for`, `loop` or `{` after a label
6+
|
7+
help: consider enclosing expression in a block
8+
|
9+
LL | 'label: {1 + 1};
10+
| + +
11+
12+
error: expected `while`, `for`, `loop` or `{` after a label
13+
--> $DIR/recover-labeled-non-block-expr.rs:7:13
14+
|
15+
LL | 'label: match () { () => break 'label, };
16+
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
17+
|
18+
help: consider enclosing expression in a block
19+
|
20+
LL | 'label: {match () { () => break 'label, }};
21+
| + +
622

7-
error[E0308]: mismatched types
8-
--> $DIR/recover-labeled-non-block-expr.rs:4:33
23+
error: expected `while`, `for`, `loop` or `{` after a label
24+
--> $DIR/recover-labeled-non-block-expr.rs:10:22
25+
|
26+
LL | let _i = 'label: match x {
27+
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
28+
|
29+
help: consider enclosing expression in a block
30+
|
31+
LL ~ let _i = 'label: {match x {
32+
LL | 0 => 42,
33+
LL | 1 if false => break 'label 17,
34+
LL | 1 => {
35+
LL | if true {
36+
LL | break 'label 13
37+
...
38+
39+
error: expected `while`, `for`, `loop` or `{` after a label
40+
--> $DIR/recover-labeled-non-block-expr.rs:24:24
41+
|
42+
LL | let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other });
43+
| ^ expected `while`, `for`, `loop` or `{` after a label
44+
|
45+
help: consider enclosing expression in a block
946
|
10-
LL | let _recovery_witness: () = 0;
11-
| -- ^ expected `()`, found integer
12-
| |
13-
| expected due to this
47+
LL | let _val = 'label: {(1, if other == 3 { break 'label (2, 3) } else { other })};
48+
| + +
1449

15-
error: aborting due to 2 previous errors
50+
error: aborting due to 4 previous errors
1651

17-
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)