Skip to content

Commit 4980b77

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 #78173
1 parent a772336 commit 4980b77

11 files changed

+241
-26
lines changed

compiler/rustc_parse/src/parser/expr.rs

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

compiler/rustc_parse/src/parser/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1299,12 +1299,11 @@ impl<'a> Parser<'a> {
12991299
}
13001300
}
13011301

1302-
/// Parses inline const expressions.
1302+
/// Parses inline const expressions. The `const` keyword was already eaten.
13031303
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
13041304
if pat {
13051305
self.psess.gated_spans.gate(sym::inline_const_pat, span);
13061306
}
1307-
self.expect_keyword(kw::Const)?;
13081307
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
13091308
let anon_const = AnonConst {
13101309
id: DUMMY_NODE_ID,

compiler/rustc_parse/src/parser/pat.rs

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

737737
if let Some(re) = self.parse_range_end() {
738738
self.parse_pat_range_begin_with(const_expr, re)?
@@ -1220,7 +1220,9 @@ impl<'a> Parser<'a> {
12201220
.then_some(self.prev_token.span);
12211221

12221222
let bound = if self.check_inline_const(0) {
1223-
self.parse_const_block(self.token.span, true)
1223+
let _eaten = self.eat_keyword(kw::Const);
1224+
debug_assert!(_eaten);
1225+
self.parse_const_block(self.prev_token.span, true)
12241226
} else if self.check_path() {
12251227
let lo = self.token.span;
12261228
let (qself, path) = if self.eat_lt() {

compiler/rustc_parse/src/parser/stmt.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -495,15 +495,21 @@ impl<'a> Parser<'a> {
495495
//
496496
// the place-inside-a-block suggestion would be more likely wrong than right.
497497
//
498+
// But we don't want to trigger this if we just parsed a pattern,
499+
// so this only triggers if the current token is neither `=>` nor `=`.
500+
//
498501
// FIXME(compiler-errors): this should probably parse an arbitrary expr and not
499502
// just lookahead one token, so we can see if there's a brace after _that_,
500503
// since we want to protect against:
501504
// `if 1 1 + 1 {` being suggested as `if { 1 } 1 + 1 {`
502505
// + +
503506
Ok(Some(_))
504-
if (!self.token.is_keyword(kw::Else)
505-
&& self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)))
506-
|| do_not_suggest_help => {}
507+
if do_not_suggest_help
508+
|| (self.token != token::FatArrow
509+
&& self.token != token::Eq
510+
&& self.look_ahead(1, |t| {
511+
t == &token::OpenDelim(token::Delimiter::Brace)
512+
})) => {}
507513
// Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
508514
Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
509515
Ok(Some(stmt)) => {
@@ -520,7 +526,7 @@ impl<'a> Parser<'a> {
520526
(stmt_span.shrink_to_lo(), "{ ".to_string()),
521527
(stmt_span.shrink_to_hi(), " }".to_string()),
522528
],
523-
// Speculative; has been misleading in the past (#46836).
529+
// Speculative; has been misleading in the past (see #46836).
524530
Applicability::MaybeIncorrect,
525531
);
526532
}

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: try placing this code inside 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
+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,60 @@
1+
//@ run-rustfix
2+
3+
// See issue #78168.
4+
5+
#![feature(inline_const_pat)]
6+
7+
// FIXME(#78171): the lint has to be allowed because of a bug
8+
#[allow(dead_code)]
9+
const fn one() -> i32 {
10+
1
11+
}
12+
13+
fn foo() -> i32 {
14+
let x = 2;
15+
16+
match x {
17+
const { 2 } => {}
18+
//~^ ERROR expected `{`, found `2`
19+
//~| HELP try placing this code inside a block
20+
_ => {}
21+
}
22+
23+
match x {
24+
const { 1 + 2 * 3 / 4 } => {}
25+
//~^ ERROR expected `{`, found `1`
26+
//~| HELP try placing this code inside a block
27+
_ => {}
28+
}
29+
30+
match x {
31+
const { one() } => {}
32+
//~^ ERROR expected `{`, found `one`
33+
//~| HELP try placing this code inside a block
34+
_ => {}
35+
}
36+
37+
x
38+
}
39+
40+
fn bar() -> i32 {
41+
let x = const { 2 };
42+
//~^ ERROR expected `{`, found `2`
43+
//~| HELP try placing this code inside a block
44+
45+
x
46+
}
47+
48+
fn baz() -> i32 {
49+
let y = const { 1 + 2 * 3 / 4 };
50+
//~^ ERROR expected `{`, found `1`
51+
//~| HELP try placing this code inside a block
52+
53+
y
54+
}
55+
56+
fn main() {
57+
foo();
58+
bar();
59+
baz();
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//@ run-rustfix
2+
3+
// See issue #78168.
4+
5+
#![feature(inline_const_pat)]
6+
7+
// FIXME(#78171): the lint has to be allowed because of a bug
8+
#[allow(dead_code)]
9+
const fn one() -> i32 {
10+
1
11+
}
12+
13+
fn foo() -> i32 {
14+
let x = 2;
15+
16+
match x {
17+
const 2 => {}
18+
//~^ ERROR expected `{`, found `2`
19+
//~| HELP try placing this code inside a block
20+
_ => {}
21+
}
22+
23+
match x {
24+
const 1 + 2 * 3 / 4 => {}
25+
//~^ ERROR expected `{`, found `1`
26+
//~| HELP try placing this code inside a block
27+
_ => {}
28+
}
29+
30+
match x {
31+
const one() => {}
32+
//~^ ERROR expected `{`, found `one`
33+
//~| HELP try placing this code inside a block
34+
_ => {}
35+
}
36+
37+
x
38+
}
39+
40+
fn bar() -> i32 {
41+
let x = const 2;
42+
//~^ ERROR expected `{`, found `2`
43+
//~| HELP try placing this code inside a block
44+
45+
x
46+
}
47+
48+
fn baz() -> i32 {
49+
let y = const 1 + 2 * 3 / 4;
50+
//~^ ERROR expected `{`, found `1`
51+
//~| HELP try placing this code inside a block
52+
53+
y
54+
}
55+
56+
fn main() {
57+
foo();
58+
bar();
59+
baz();
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
error: expected `{`, found `2`
2+
--> $DIR/inline-const-without-block.rs:17:15
3+
|
4+
LL | const 2 => {}
5+
| ^ expected `{`
6+
|
7+
help: try placing this code inside a block
8+
|
9+
LL | const { 2 } => {}
10+
| + +
11+
12+
error: expected `{`, found `1`
13+
--> $DIR/inline-const-without-block.rs:24:15
14+
|
15+
LL | const 1 + 2 * 3 / 4 => {}
16+
| ^ expected `{`
17+
|
18+
help: try placing this code inside a block
19+
|
20+
LL | const { 1 + 2 * 3 / 4 } => {}
21+
| + +
22+
23+
error: expected `{`, found `one`
24+
--> $DIR/inline-const-without-block.rs:31:15
25+
|
26+
LL | const one() => {}
27+
| ^^^ expected `{`
28+
|
29+
help: try placing this code inside a block
30+
|
31+
LL | const { one() } => {}
32+
| + +
33+
34+
error: expected `{`, found `2`
35+
--> $DIR/inline-const-without-block.rs:41:19
36+
|
37+
LL | let x = const 2;
38+
| ^ expected `{`
39+
|
40+
help: try placing this code inside a block
41+
|
42+
LL | let x = const { 2 };
43+
| + +
44+
45+
error: expected `{`, found `1`
46+
--> $DIR/inline-const-without-block.rs:49:19
47+
|
48+
LL | let y = const 1 + 2 * 3 / 4;
49+
| ^ expected `{`
50+
|
51+
help: try placing this code inside 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)