Skip to content

Commit a49aece

Browse files
camelidGrigorenkoPV
authored andcommitted
Suggest adding missing braces in const block pattern
Previously it would only suggest wrapping the code in braces in regular expressions; now it does it in patterns too. This is a squashed rebase of rust-lang#78173
1 parent 0e98766 commit a49aece

13 files changed

+254
-40
lines changed

compiler/rustc_parse/src/parser/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1473,8 +1473,8 @@ impl<'a> Parser<'a> {
14731473
err
14741474
},
14751475
)
1476-
} else if this.check_inline_const(0) {
1477-
this.parse_const_block(lo, false)
1476+
} else if this.eat_keyword(kw::Const) {
1477+
this.parse_const_block(lo.to(this.prev_token.span), false)
14781478
} else if this.may_recover() && this.is_do_catch_block() {
14791479
this.recover_do_catch()
14801480
} else if this.is_try_block() {

compiler/rustc_parse/src/parser/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1314,12 +1314,11 @@ impl<'a> Parser<'a> {
13141314
}
13151315
}
13161316

1317-
/// Parses inline const expressions.
1317+
/// Parses inline const expressions. The `const` keyword was already eaten.
13181318
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
13191319
if pat {
13201320
self.psess.gated_spans.gate(sym::inline_const_pat, span);
13211321
}
1322-
self.expect_keyword(kw::Const)?;
13231322
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
13241323
let anon_const = AnonConst {
13251324
id: DUMMY_NODE_ID,

compiler/rustc_parse/src/parser/pat.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,9 @@ impl<'a> Parser<'a> {
733733
self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)?
734734
} else if self.eat_keyword(kw::Box) {
735735
self.parse_pat_box()?
736-
} else if self.check_inline_const(0) {
737-
// Parse `const pat`
738-
let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;
736+
} else if self.eat_keyword(kw::Const) {
737+
// Parse `const { pat }`
738+
let const_expr = self.parse_const_block(lo.to(self.prev_token.span), true)?;
739739

740740
if let Some(re) = self.parse_range_end() {
741741
self.parse_pat_range_begin_with(const_expr, re)?
@@ -1225,7 +1225,9 @@ impl<'a> Parser<'a> {
12251225
.then_some(self.prev_token.span);
12261226

12271227
let bound = if self.check_inline_const(0) {
1228-
self.parse_const_block(self.token.span, true)
1228+
let _eaten = self.eat_keyword(kw::Const);
1229+
debug_assert!(_eaten);
1230+
self.parse_const_block(self.prev_token.span, true)
12291231
} else if self.check_path() {
12301232
let lo = self.token.span;
12311233
let (qself, path) = if self.eat_lt() {

compiler/rustc_parse/src/parser/stmt.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -497,15 +497,21 @@ impl<'a> Parser<'a> {
497497
//
498498
// the place-inside-a-block suggestion would be more likely wrong than right.
499499
//
500+
// But we don't want to trigger this if we just parsed a pattern,
501+
// so this only triggers if the current token is neither `=>` nor `=`.
502+
//
500503
// FIXME(compiler-errors): this should probably parse an arbitrary expr and not
501504
// just lookahead one token, so we can see if there's a brace after _that_,
502505
// since we want to protect against:
503506
// `if 1 1 + 1 {` being suggested as `if { 1 } 1 + 1 {`
504507
// + +
505508
Ok(Some(_))
506-
if (!self.token.is_keyword(kw::Else)
507-
&& self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)))
508-
|| do_not_suggest_help => {}
509+
if do_not_suggest_help
510+
|| (self.token != token::FatArrow
511+
&& self.token != token::Eq
512+
&& self.look_ahead(1, |t| {
513+
t == &token::OpenDelim(token::Delimiter::Brace)
514+
})) => {}
509515
// Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
510516
Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
511517
Ok(Some(stmt)) => {

tests/ui/parser/bad-if-statements.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ note: the `if` expression is missing a block after this condition
6565
|
6666
LL | if true x else {}
6767
| ^^^^
68-
help: you might have meant to write this as part of a block
69-
|
70-
LL | if true { x } else {}
71-
| + +
7268

7369
error: this `if` expression is missing a block after the condition
7470
--> $DIR/bad-if-statements.rs:34:5

tests/ui/parser/block-no-opening-brace.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ edition:2018
22

3-
#![feature(try_blocks)]
3+
#![feature(try_blocks, inline_const_pat)]
44

55
fn main() {}
66

@@ -35,15 +35,14 @@ fn in_async() {
3535

3636
// FIXME(#78168)
3737
fn in_const() {
38-
let x = const 2; //~ ERROR expected expression, found keyword `const`
38+
let x = const 2; //~ ERROR expected `{`, found `2`
3939
}
4040

4141
// FIXME(#78168)
4242
fn in_const_in_match() {
4343
let x = 2;
4444
match x {
4545
const 2 => {}
46-
//~^ ERROR expected identifier, found keyword `const`
47-
//~| ERROR expected one of `=>`, `if`, or `|`, found `2`
46+
//~^ ERROR expected `{`, found `2`
4847
}
4948
}

tests/ui/parser/block-no-opening-brace.stderr

+15-11
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,27 @@ LL | async
5151
LL | let x = 0;
5252
| ^^^ unexpected token
5353

54-
error: expected expression, found keyword `const`
55-
--> $DIR/block-no-opening-brace.rs:38:13
54+
error: expected `{`, found `2`
55+
--> $DIR/block-no-opening-brace.rs:38:19
5656
|
5757
LL | let x = const 2;
58-
| ^^^^^ expected expression
59-
60-
error: expected identifier, found keyword `const`
61-
--> $DIR/block-no-opening-brace.rs:45:9
58+
| ^ expected `{`
6259
|
63-
LL | const 2 => {}
64-
| ^^^^^ expected identifier, found keyword
60+
help: you might have meant to write this as part of a block
61+
|
62+
LL | let x = const { 2 };
63+
| + +
6564

66-
error: expected one of `=>`, `if`, or `|`, found `2`
65+
error: expected `{`, found `2`
6766
--> $DIR/block-no-opening-brace.rs:45:15
6867
|
6968
LL | const 2 => {}
70-
| ^ expected one of `=>`, `if`, or `|`
69+
| ^ expected `{`
70+
|
71+
help: you might have meant to write this as part of a block
72+
|
73+
LL | const { 2 } => {}
74+
| + +
7175

72-
error: aborting due to 8 previous errors
76+
error: aborting due to 7 previous errors
7377

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-pass
2+
3+
#![feature(inline_const_pat)]
4+
5+
fn if_let_1() -> i32 {
6+
let x = 2;
7+
const Y: i32 = 3;
8+
9+
if let const { (Y + 1) / 2 } = x {
10+
x
11+
} else {
12+
0
13+
}
14+
}
15+
16+
fn if_let_2() -> i32 {
17+
let x = 2;
18+
19+
if let const { 1 + 2 } = x {
20+
const { 1 + 2 }
21+
} else {
22+
0
23+
}
24+
}
25+
26+
fn main() {
27+
assert_eq!(if_let_1(), 2);
28+
assert_eq!(if_let_2(), 0);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//@ run-rustfix
2+
3+
// See issue #78168.
4+
5+
#![feature(inline_const_pat)]
6+
7+
const fn one() -> i32 {
8+
1
9+
}
10+
11+
fn foo() -> i32 {
12+
let x = 2;
13+
14+
match x {
15+
const { 2 } => {}
16+
//~^ ERROR expected `{`, found `2`
17+
//~| HELP you might have meant to write this as part of a block
18+
_ => {}
19+
}
20+
21+
match x {
22+
const { 1 + 2 * 3 / 4 } => {}
23+
//~^ ERROR expected `{`, found `1`
24+
//~| HELP you might have meant to write this as part of a block
25+
_ => {}
26+
}
27+
28+
match x {
29+
const { one() } => {}
30+
//~^ ERROR expected `{`, found `one`
31+
//~| HELP you might have meant to write this as part of a block
32+
_ => {}
33+
}
34+
35+
x
36+
}
37+
38+
fn bar() -> i32 {
39+
let x = const { 2 };
40+
//~^ ERROR expected `{`, found `2`
41+
//~| HELP you might have meant to write this as part of a block
42+
43+
x
44+
}
45+
46+
fn baz() -> i32 {
47+
let y = const { 1 + 2 * 3 / 4 };
48+
//~^ ERROR expected `{`, found `1`
49+
//~| HELP you might have meant to write this as part of a block
50+
51+
y
52+
}
53+
54+
fn main() {
55+
foo();
56+
bar();
57+
baz();
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//@ run-rustfix
2+
3+
// See issue #78168.
4+
5+
#![feature(inline_const_pat)]
6+
7+
const fn one() -> i32 {
8+
1
9+
}
10+
11+
fn foo() -> i32 {
12+
let x = 2;
13+
14+
match x {
15+
const 2 => {}
16+
//~^ ERROR expected `{`, found `2`
17+
//~| HELP you might have meant to write this as part of a block
18+
_ => {}
19+
}
20+
21+
match x {
22+
const 1 + 2 * 3 / 4 => {}
23+
//~^ ERROR expected `{`, found `1`
24+
//~| HELP you might have meant to write this as part of a block
25+
_ => {}
26+
}
27+
28+
match x {
29+
const one() => {}
30+
//~^ ERROR expected `{`, found `one`
31+
//~| HELP you might have meant to write this as part of a block
32+
_ => {}
33+
}
34+
35+
x
36+
}
37+
38+
fn bar() -> i32 {
39+
let x = const 2;
40+
//~^ ERROR expected `{`, found `2`
41+
//~| HELP you might have meant to write this as part of a block
42+
43+
x
44+
}
45+
46+
fn baz() -> i32 {
47+
let y = const 1 + 2 * 3 / 4;
48+
//~^ ERROR expected `{`, found `1`
49+
//~| HELP you might have meant to write this as part of a block
50+
51+
y
52+
}
53+
54+
fn main() {
55+
foo();
56+
bar();
57+
baz();
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
error: expected `{`, found `2`
2+
--> $DIR/inline-const-without-block.rs:15:15
3+
|
4+
LL | const 2 => {}
5+
| ^ expected `{`
6+
|
7+
help: you might have meant to write this as part of a block
8+
|
9+
LL | const { 2 } => {}
10+
| + +
11+
12+
error: expected `{`, found `1`
13+
--> $DIR/inline-const-without-block.rs:22:15
14+
|
15+
LL | const 1 + 2 * 3 / 4 => {}
16+
| ^ expected `{`
17+
|
18+
help: you might have meant to write this as part of a block
19+
|
20+
LL | const { 1 + 2 * 3 / 4 } => {}
21+
| + +
22+
23+
error: expected `{`, found `one`
24+
--> $DIR/inline-const-without-block.rs:29:15
25+
|
26+
LL | const one() => {}
27+
| ^^^ expected `{`
28+
|
29+
help: you might have meant to write this as part of a block
30+
|
31+
LL | const { one() } => {}
32+
| + +
33+
34+
error: expected `{`, found `2`
35+
--> $DIR/inline-const-without-block.rs:39:19
36+
|
37+
LL | let x = const 2;
38+
| ^ expected `{`
39+
|
40+
help: you might have meant to write this as part of a block
41+
|
42+
LL | let x = const { 2 };
43+
| + +
44+
45+
error: expected `{`, found `1`
46+
--> $DIR/inline-const-without-block.rs:47:19
47+
|
48+
LL | let y = const 1 + 2 * 3 / 4;
49+
| ^ expected `{`
50+
|
51+
help: you might have meant to write this as part of a block
52+
|
53+
LL | let y = const { 1 + 2 * 3 / 4 };
54+
| + +
55+
56+
error: aborting due to 5 previous errors
57+
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// This file was auto-generated using 'src/etc/generate-keyword-tests.py const'
2-
31
fn main() {
4-
let const = "foo"; //~ error: expected identifier, found keyword `const`
2+
let const = "foo";
3+
//~^ ERROR expected `{`, found `=`
4+
//~| ERROR inline-const in pattern position is experimental [E0658]
55
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
error: expected identifier, found keyword `const`
2-
--> $DIR/keyword-const-as-identifier.rs:4:9
1+
error: expected `{`, found `=`
2+
--> $DIR/keyword-const-as-identifier.rs:2:15
33
|
44
LL | let const = "foo";
5-
| ^^^^^ expected identifier, found keyword
5+
| ^ expected `{`
6+
7+
error[E0658]: inline-const in pattern position is experimental
8+
--> $DIR/keyword-const-as-identifier.rs:2:9
69
|
7-
help: escape `const` to use it as an identifier
10+
LL | let const = "foo";
11+
| ^^^^^
812
|
9-
LL | let r#const = "foo";
10-
| ++
13+
= note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
14+
= help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
15+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1116

12-
error: aborting due to 1 previous error
17+
error: aborting due to 2 previous errors
1318

19+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)