Skip to content

Commit b0a0759

Browse files
committed
Auto merge of rust-lang#117289 - estebank:issue-72298, r=cjgillot
Account for `ref` and `mut` in the wrong place for pattern ident renaming If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest the correct code. Fix rust-lang#72298.
2 parents f3457db + b589f47 commit b0a0759

File tree

4 files changed

+127
-1
lines changed

4 files changed

+127
-1
lines changed

compiler/rustc_parse/src/parser/pat.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -967,11 +967,12 @@ impl<'a> Parser<'a> {
967967

968968
// check that a comma comes after every field
969969
if !ate_comma {
970-
let err = ExpectedCommaAfterPatternField { span: self.token.span }
970+
let mut err = ExpectedCommaAfterPatternField { span: self.token.span }
971971
.into_diagnostic(&self.sess.span_diagnostic);
972972
if let Some(mut delayed) = delayed_err {
973973
delayed.emit();
974974
}
975+
self.recover_misplaced_pattern_modifiers(&fields, &mut err);
975976
return Err(err);
976977
}
977978
ate_comma = false;
@@ -1109,6 +1110,37 @@ impl<'a> Parser<'a> {
11091110
Ok((fields, etc))
11101111
}
11111112

1113+
/// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest
1114+
/// the correct code.
1115+
fn recover_misplaced_pattern_modifiers(
1116+
&self,
1117+
fields: &ThinVec<PatField>,
1118+
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
1119+
) {
1120+
if let Some(last) = fields.iter().last()
1121+
&& last.is_shorthand
1122+
&& let PatKind::Ident(binding, ident, None) = last.pat.kind
1123+
&& binding != BindingAnnotation::NONE
1124+
&& self.token == token::Colon
1125+
// We found `ref mut? ident:`, try to parse a `name,` or `name }`.
1126+
&& let Some(name_span) = self.look_ahead(1, |t| t.is_ident().then(|| t.span))
1127+
&& self.look_ahead(2, |t| {
1128+
t == &token::Comma || t == &token::CloseDelim(Delimiter::Brace)
1129+
})
1130+
{
1131+
let span = last.pat.span.with_hi(ident.span.lo());
1132+
// We have `S { ref field: name }` instead of `S { field: ref name }`
1133+
err.multipart_suggestion(
1134+
"the pattern modifiers belong after the `:`",
1135+
vec![
1136+
(span, String::new()),
1137+
(name_span.shrink_to_lo(), binding.prefix_str().to_string()),
1138+
],
1139+
Applicability::MachineApplicable,
1140+
);
1141+
}
1142+
}
1143+
11121144
/// Recover on `...` or `_` as if it were `..` to avoid further errors.
11131145
/// See issue #46718.
11141146
fn recover_bad_dot_dot(&self) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// run-rustfix
2+
struct S {
3+
field_name: (),
4+
}
5+
6+
fn main() {
7+
match (S {field_name: ()}) {
8+
S {field_name: ref _foo} => {} //~ ERROR expected `,`
9+
}
10+
match (S {field_name: ()}) {
11+
S {field_name: mut _foo} => {} //~ ERROR expected `,`
12+
}
13+
match (S {field_name: ()}) {
14+
S {field_name: ref mut _foo} => {} //~ ERROR expected `,`
15+
}
16+
// Verify that we recover enough to run typeck.
17+
let _: usize = 3usize; //~ ERROR mismatched types
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// run-rustfix
2+
struct S {
3+
field_name: (),
4+
}
5+
6+
fn main() {
7+
match (S {field_name: ()}) {
8+
S {ref field_name: _foo} => {} //~ ERROR expected `,`
9+
}
10+
match (S {field_name: ()}) {
11+
S {mut field_name: _foo} => {} //~ ERROR expected `,`
12+
}
13+
match (S {field_name: ()}) {
14+
S {ref mut field_name: _foo} => {} //~ ERROR expected `,`
15+
}
16+
// Verify that we recover enough to run typeck.
17+
let _: usize = 3u8; //~ ERROR mismatched types
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error: expected `,`
2+
--> $DIR/incorrect-placement-of-pattern-modifiers.rs:8:26
3+
|
4+
LL | S {ref field_name: _foo} => {}
5+
| - ^
6+
| |
7+
| while parsing the fields for this pattern
8+
|
9+
help: the pattern modifiers belong after the `:`
10+
|
11+
LL - S {ref field_name: _foo} => {}
12+
LL + S {field_name: ref _foo} => {}
13+
|
14+
15+
error: expected `,`
16+
--> $DIR/incorrect-placement-of-pattern-modifiers.rs:11:26
17+
|
18+
LL | S {mut field_name: _foo} => {}
19+
| - ^
20+
| |
21+
| while parsing the fields for this pattern
22+
|
23+
help: the pattern modifiers belong after the `:`
24+
|
25+
LL - S {mut field_name: _foo} => {}
26+
LL + S {field_name: mut _foo} => {}
27+
|
28+
29+
error: expected `,`
30+
--> $DIR/incorrect-placement-of-pattern-modifiers.rs:14:30
31+
|
32+
LL | S {ref mut field_name: _foo} => {}
33+
| - ^
34+
| |
35+
| while parsing the fields for this pattern
36+
|
37+
help: the pattern modifiers belong after the `:`
38+
|
39+
LL - S {ref mut field_name: _foo} => {}
40+
LL + S {field_name: ref mut _foo} => {}
41+
|
42+
43+
error[E0308]: mismatched types
44+
--> $DIR/incorrect-placement-of-pattern-modifiers.rs:17:20
45+
|
46+
LL | let _: usize = 3u8;
47+
| ----- ^^^ expected `usize`, found `u8`
48+
| |
49+
| expected due to this
50+
|
51+
help: change the type of the numeric literal from `u8` to `usize`
52+
|
53+
LL | let _: usize = 3usize;
54+
| ~~~~~
55+
56+
error: aborting due to 4 previous errors
57+
58+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)