Skip to content

Commit dac8c88

Browse files
committed
Add const VAL = ... suggestion
1 parent 1940310 commit dac8c88

17 files changed

+386
-125
lines changed

compiler/rustc_parse/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -786,10 +786,10 @@ parse_unexpected_expr_in_pat =
786786
*[false] arbitrary expressions
787787
} are not allowed in patterns
788788
789-
.help = extract the expression into a `const` and refer to it
790-
791789
parse_unexpected_expr_in_pat_const_pat_sugg = wrap the expression in a inline const (requires `{"#"}![feature(inline_const)]`)
792790
791+
parse_unexpected_expr_in_pat_const_sugg = extract the expression into a `const` and refer to it
792+
793793
parse_unexpected_if_with_if = unexpected `if` in the condition expression
794794
.suggestion = remove the `if`
795795

compiler/rustc_parse/src/errors.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -2433,7 +2433,6 @@ pub(crate) struct ExpectedCommaAfterPatternField {
24332433

24342434
#[derive(Diagnostic)]
24352435
#[diag(parse_unexpected_expr_in_pat)]
2436-
#[help]
24372436
pub(crate) struct UnexpectedExpressionInPattern {
24382437
#[primary_span]
24392438
#[label]
@@ -2447,7 +2446,7 @@ pub(crate) struct UnexpectedExpressionInPattern {
24472446
#[derive(Subdiagnostic)]
24482447
#[multipart_suggestion(
24492448
parse_unexpected_expr_in_pat_const_pat_sugg,
2450-
applicability = "machine-applicable"
2449+
applicability = "maybe-incorrect"
24512450
)]
24522451
pub(crate) struct UnexpectedExpressionInPatternConstPatSugg {
24532452
#[suggestion_part(code = "const {{ ")]
@@ -2456,6 +2455,17 @@ pub(crate) struct UnexpectedExpressionInPatternConstPatSugg {
24562455
pub end_span: Span,
24572456
}
24582457

2458+
#[derive(Subdiagnostic)]
2459+
#[multipart_suggestion(parse_unexpected_expr_in_pat_const_sugg, applicability = "has-placeholders")]
2460+
pub(crate) struct UnexpectedExpressionInPatternConstSugg {
2461+
#[suggestion_part(code = "{indentation}const VAL: _ = {expr};\n")]
2462+
pub const_span: Span,
2463+
#[suggestion_part(code = "VAL")]
2464+
pub pat_span: Span,
2465+
pub expr: String,
2466+
pub indentation: String,
2467+
}
2468+
24592469
#[derive(Diagnostic)]
24602470
#[diag(parse_unexpected_paren_in_range_pat)]
24612471
pub(crate) struct UnexpectedParenInRangePat {

compiler/rustc_parse/src/parser/item.rs

+48-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::{
44
AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Recovered, Trailing,
55
TrailingToken,
66
};
7-
use crate::errors::{self, MacroExpandsToAdtField};
7+
use crate::errors::{self, MacroExpandsToAdtField, UnexpectedExpressionInPatternConstSugg};
88
use crate::fluent_generated as fluent;
99
use crate::maybe_whole;
1010
use ast::token::IdentIsRaw;
@@ -13,6 +13,7 @@ use rustc_ast::ptr::P;
1313
use rustc_ast::token::{self, Delimiter, TokenKind};
1414
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
1515
use rustc_ast::util::case::Case;
16+
use rustc_ast::visit::{walk_pat, walk_stmt, Visitor};
1617
use rustc_ast::{self as ast};
1718
use rustc_ast_pretty::pprust;
1819
use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey};
@@ -2362,6 +2363,52 @@ impl<'a> Parser<'a> {
23622363
}
23632364
(AttrVec::new(), None)
23642365
};
2366+
2367+
if let Some(body) = &body {
2368+
struct PatVisitor<'a> {
2369+
parser: &'a Parser<'a>,
2370+
stmt: Option<&'a Stmt>,
2371+
}
2372+
2373+
impl<'a> Visitor<'a> for PatVisitor<'a> {
2374+
fn visit_stmt(&mut self, s: &'a Stmt) -> Self::Result {
2375+
self.stmt = Some(s);
2376+
2377+
walk_stmt(self, s)
2378+
}
2379+
2380+
fn visit_pat(&mut self, pat: &'a Pat) -> Self::Result {
2381+
if matches!(pat.kind, PatKind::Err(_)) {
2382+
let sm = self.parser.psess.source_map();
2383+
2384+
self.parser.dcx().try_steal_modify_and_emit_err(
2385+
pat.span,
2386+
StashKey::ExprInPat,
2387+
|err| {
2388+
err.subdiagnostic(
2389+
&self.parser.dcx(),
2390+
UnexpectedExpressionInPatternConstSugg {
2391+
const_span: sm
2392+
.span_extend_to_line(self.stmt.unwrap().span)
2393+
.shrink_to_lo(),
2394+
pat_span: pat.span,
2395+
expr: self.parser.span_to_snippet(pat.span).unwrap(),
2396+
indentation: sm
2397+
.indentation_before(self.stmt.unwrap().span)
2398+
.unwrap_or_default(),
2399+
},
2400+
);
2401+
},
2402+
);
2403+
}
2404+
2405+
walk_pat(self, pat)
2406+
}
2407+
}
2408+
2409+
PatVisitor { parser: self, stmt: None }.visit_block(body);
2410+
}
2411+
23652412
attrs.extend(inner_attrs);
23662413
Ok(body)
23672414
}

compiler/rustc_parse/src/parser/pat.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ impl<'a> Parser<'a> {
361361
let is_float_literal = |that: &Self, token: &Token| -> bool {
362362
use token::{Lit, LitKind};
363363

364-
let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind else {
364+
let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind
365+
else {
365366
return false;
366367
};
367368

@@ -594,16 +595,19 @@ impl<'a> Parser<'a> {
594595
} else {
595596
// Try to parse everything else as literal with optional minus
596597
match self.parse_literal_maybe_minus() {
597-
Ok(begin) => {
598-
let begin = match self.maybe_recover_trailing_expr(begin.span, false) {
599-
Some((guar, sp)) => self.mk_expr_err(sp, guar),
600-
None => begin,
601-
};
602-
603-
match self.parse_range_end() {
598+
Ok(mut begin) => {
599+
let guar =
600+
self.maybe_recover_trailing_expr(begin.span, false).map(|(guar, sp)| {
601+
begin = self.mk_expr_err(sp, guar);
602+
guar
603+
});
604+
605+
let pat = match self.parse_range_end() {
604606
Some(form) => self.parse_pat_range_begin_with(begin, form)?,
605607
None => PatKind::Lit(begin),
606-
}
608+
};
609+
610+
if let Some(guar) = guar { PatKind::Err(guar) } else { pat }
607611
}
608612
Err(err) => return self.fatal_unexpected_non_pat(err, expected),
609613
}

tests/ui/half-open-range-patterns/range_pat_interactions1.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ error: expected a pattern range bound, found an expression
9999
LL | 0..5+1 => errors_only.push(x),
100100
| ^^^ arbitrary expressions are not allowed in patterns
101101
|
102-
= help: extract the expression into a `const` and refer to it
103102
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
104103
|
105104
LL | 0..const { 5+1 } => errors_only.push(x),

tests/ui/half-open-range-patterns/range_pat_interactions2.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ error: expected a pattern range bound, found an expression
7070
LL | 0..=(5+1) => errors_only.push(x),
7171
| ^^^ arbitrary expressions are not allowed in patterns
7272
|
73-
= help: extract the expression into a `const` and refer to it
7473
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
7574
|
7675
LL | 0..=(const { 5+1 }) => errors_only.push(x),

tests/ui/parser/bad-name.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ error: expected a pattern, found an expression
1616
LL | let x.y::<isize>.z foo;
1717
| ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
1818
|
19-
= help: extract the expression into a `const` and refer to it
2019
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
2120
|
2221
LL | let const { x.y::<isize>.z } foo;

tests/ui/parser/issues/issue-24197.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ error: expected a pattern, found an expression
44
LL | let buf[0] = 0;
55
| ^^^^^^ arbitrary expressions are not allowed in patterns
66
|
7-
= help: extract the expression into a `const` and refer to it
87
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
98
|
109
LL | let const { buf[0] } = 0;
1110
| +++++++ +
11+
help: extract the expression into a `const` and refer to it
12+
|
13+
LL + const VAL: _ = buf[0];
14+
LL ~ let VAL = 0;
15+
|
1216

1317
error: aborting due to 1 previous error
1418

tests/ui/parser/issues/issue-24375.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ error: expected a pattern, found an expression
44
LL | tmp[0] => {}
55
| ^^^^^^ arbitrary expressions are not allowed in patterns
66
|
7-
= help: extract the expression into a `const` and refer to it
87
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
98
|
109
LL | const { tmp[0] } => {}
1110
| +++++++ +
11+
help: extract the expression into a `const` and refer to it
12+
|
13+
LL + const VAL: _ = tmp[0];
14+
LL ~ match z {
15+
LL ~ VAL => {}
16+
|
1217

1318
error: aborting due to 1 previous error
1419

tests/ui/parser/pat-lt-bracket-5.stderr

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
error[E0425]: cannot find value `v` in this scope
2-
--> $DIR/pat-lt-bracket-5.rs:2:16
3-
|
4-
LL | let v[0] = v[1];
5-
| ^ not found in this scope
6-
71
error: expected a pattern, found an expression
82
--> $DIR/pat-lt-bracket-5.rs:2:9
93
|
104
LL | let v[0] = v[1];
115
| ^^^^ arbitrary expressions are not allowed in patterns
126
|
13-
= help: extract the expression into a `const` and refer to it
147
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
158
|
169
LL | let const { v[0] } = v[1];
1710
| +++++++ +
11+
help: extract the expression into a `const` and refer to it
12+
|
13+
LL + const VAL: _ = v[0];
14+
LL ~ let VAL = v[1];
15+
|
16+
17+
error[E0425]: cannot find value `v` in this scope
18+
--> $DIR/pat-lt-bracket-5.rs:2:16
19+
|
20+
LL | let v[0] = v[1];
21+
| ^ not found in this scope
1822

1923
error: aborting due to 2 previous errors
2024

tests/ui/parser/pat-lt-bracket-6.stderr

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
error: expected a pattern, found an expression
2+
--> $DIR/pat-lt-bracket-6.rs:5:15
3+
|
4+
LL | let Test(&desc[..]) = x;
5+
| ^^^^^^^^ arbitrary expressions are not allowed in patterns
6+
|
7+
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
8+
|
9+
LL | let Test(&const { desc[..] }) = x;
10+
| +++++++ +
11+
help: extract the expression into a `const` and refer to it
12+
|
13+
LL + const VAL: _ = desc[..];
14+
LL ~ let Test(&VAL) = x;
15+
|
16+
117
error[E0308]: mismatched types
218
--> $DIR/pat-lt-bracket-6.rs:10:30
319
|
@@ -18,18 +34,6 @@ help: use `_` to explicitly ignore each field
1834
LL | let Test(&desc[..], _) = x;
1935
| +++
2036

21-
error: expected a pattern, found an expression
22-
--> $DIR/pat-lt-bracket-6.rs:5:15
23-
|
24-
LL | let Test(&desc[..]) = x;
25-
| ^^^^^^^^ arbitrary expressions are not allowed in patterns
26-
|
27-
= help: extract the expression into a `const` and refer to it
28-
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
29-
|
30-
LL | let Test(&const { desc[..] }) = x;
31-
| +++++++ +
32-
3337
error: aborting due to 3 previous errors
3438

3539
Some errors have detailed explanations: E0023, E0308.

tests/ui/parser/pat-ranges-3.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error: expected a pattern range bound, found an expression
44
LL | let 10 ..= 10 + 3 = 12;
55
| ^^^^^^ arbitrary expressions are not allowed in patterns
66
|
7-
= help: extract the expression into a `const` and refer to it
87
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
98
|
109
LL | let 10 ..= const { 10 + 3 } = 12;
@@ -16,7 +15,6 @@ error: expected a pattern range bound, found an expression
1615
LL | let 10 - 3 ..= 10 = 8;
1716
| ^^^^^^ arbitrary expressions are not allowed in patterns
1817
|
19-
= help: extract the expression into a `const` and refer to it
2018
help: wrap the expression in a inline const (requires `#![feature(inline_const)]`)
2119
|
2220
LL | let const { 10 - 3 } ..= 10 = 8;

0 commit comments

Comments
 (0)