@@ -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 ) {
0 commit comments