Skip to content

Commit 505e128

Browse files
committed
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 #72298.
1 parent 6f65201 commit 505e128

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

compiler/rustc_parse/src/parser/pat.rs

Lines changed: 39 additions & 1 deletion
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,43 @@ 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+
&& self.look_ahead(1, |t| t.is_ident())
1126+
&& self.look_ahead(2, |t| {
1127+
t == &token::Comma || t == &token::CloseDelim(Delimiter::Brace)
1128+
})
1129+
&& let span = last.pat.span.with_hi(ident.span.lo())
1130+
&& let Ok(snippet) = self.sess.source_map().span_to_snippet(span)
1131+
{
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+
(
1138+
self.token
1139+
.span
1140+
.shrink_to_hi()
1141+
.with_hi(self.look_ahead(1, |t| t.span.lo())),
1142+
format!(" {snippet}"),
1143+
),
1144+
],
1145+
Applicability::MachineApplicable,
1146+
);
1147+
}
1148+
}
1149+
11121150
/// Recover on `...` or `_` as if it were `..` to avoid further errors.
11131151
/// See issue #46718.
11141152
fn recover_bad_dot_dot(&self) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
let _: usize = 3usize; //~ ERROR mismatched types
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
let _: usize = 3u8; //~ ERROR mismatched types
11+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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[E0308]: mismatched types
16+
--> $DIR/incorrect-placement-of-pattern-modifiers.rs:10:20
17+
|
18+
LL | let _: usize = 3u8;
19+
| ----- ^^^ expected `usize`, found `u8`
20+
| |
21+
| expected due to this
22+
|
23+
help: change the type of the numeric literal from `u8` to `usize`
24+
|
25+
LL | let _: usize = 3usize;
26+
| ~~~~~
27+
28+
error: aborting due to 2 previous errors
29+
30+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)