@@ -156,6 +156,52 @@ impl AttemptLocalParseRecovery {
156
156
}
157
157
}
158
158
159
+ #[ derive( Debug , Copy , Clone ) ]
160
+ struct IncDecRecovery {
161
+ standalone : bool ,
162
+ op : IncOrDec ,
163
+ fixity : UnaryFixity ,
164
+ }
165
+
166
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
167
+ enum IncOrDec {
168
+ Inc ,
169
+ // FIXME: `i--` recovery isn't implemented yet
170
+ #[ allow( dead_code) ]
171
+ Dec ,
172
+ }
173
+
174
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
175
+ enum UnaryFixity {
176
+ Pre ,
177
+ Post ,
178
+ }
179
+
180
+ impl IncOrDec {
181
+ fn chr ( & self ) -> char {
182
+ match self {
183
+ Self :: Inc => '+' ,
184
+ Self :: Dec => '-' ,
185
+ }
186
+ }
187
+
188
+ fn name ( & self ) -> & ' static str {
189
+ match self {
190
+ Self :: Inc => "increment" ,
191
+ Self :: Dec => "decrement" ,
192
+ }
193
+ }
194
+ }
195
+
196
+ impl std:: fmt:: Display for UnaryFixity {
197
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
198
+ match self {
199
+ Self :: Pre => write ! ( f, "prefix" ) ,
200
+ Self :: Post => write ! ( f, "postfix" ) ,
201
+ }
202
+ }
203
+ }
204
+
159
205
// SnapshotParser is used to create a snapshot of the parser
160
206
// without causing duplicate errors being emitted when the `Parser`
161
207
// is dropped.
@@ -1167,6 +1213,145 @@ impl<'a> Parser<'a> {
1167
1213
Ok ( ( ) )
1168
1214
}
1169
1215
1216
+ pub ( super ) fn maybe_recover_from_prefix_increment (
1217
+ & mut self ,
1218
+ operand_expr : P < Expr > ,
1219
+ op_span : Span ,
1220
+ prev_is_semi : bool ,
1221
+ ) -> PResult < ' a , P < Expr > > {
1222
+ let kind = IncDecRecovery {
1223
+ standalone : prev_is_semi,
1224
+ op : IncOrDec :: Inc ,
1225
+ fixity : UnaryFixity :: Pre ,
1226
+ } ;
1227
+
1228
+ self . recover_from_inc_dec ( operand_expr, kind, op_span)
1229
+ }
1230
+
1231
+ pub ( super ) fn maybe_recover_from_postfix_increment (
1232
+ & mut self ,
1233
+ operand_expr : P < Expr > ,
1234
+ op_span : Span ,
1235
+ prev_is_semi : bool ,
1236
+ ) -> PResult < ' a , P < Expr > > {
1237
+ let kind = IncDecRecovery {
1238
+ standalone : prev_is_semi,
1239
+ op : IncOrDec :: Inc ,
1240
+ fixity : UnaryFixity :: Post ,
1241
+ } ;
1242
+
1243
+ self . recover_from_inc_dec ( operand_expr, kind, op_span)
1244
+ }
1245
+
1246
+ fn recover_from_inc_dec (
1247
+ & mut self ,
1248
+ base : P < Expr > ,
1249
+ kind : IncDecRecovery ,
1250
+ op_span : Span ,
1251
+ ) -> PResult < ' a , P < Expr > > {
1252
+ let mut err = self . struct_span_err (
1253
+ op_span,
1254
+ & format ! ( "Rust has no {} {} operator" , kind. fixity, kind. op. name( ) ) ,
1255
+ ) ;
1256
+ err. span_label ( op_span, & format ! ( "not a valid {} operator" , kind. fixity) ) ;
1257
+
1258
+ if let ExprKind :: Path ( _, path) = & base. kind {
1259
+ if let [ segment] = path. segments . as_slice ( ) {
1260
+ let ident = segment. ident ;
1261
+ // (pre, post)
1262
+ let spans = match kind. fixity {
1263
+ UnaryFixity :: Pre => ( op_span, ident. span . shrink_to_hi ( ) ) ,
1264
+ UnaryFixity :: Post => ( ident. span . shrink_to_lo ( ) , op_span) ,
1265
+ } ;
1266
+
1267
+ if !ident. is_reserved ( ) {
1268
+ if kind. standalone {
1269
+ return self . inc_dec_standalone_recovery ( base, err, kind, ident, spans) ;
1270
+ } else {
1271
+ match kind. fixity {
1272
+ UnaryFixity :: Pre => {
1273
+ return self . prefix_inc_dec_suggest_and_recover (
1274
+ base, err, kind, ident, spans,
1275
+ ) ;
1276
+ }
1277
+ UnaryFixity :: Post => {
1278
+ return self . postfix_inc_dec_suggest_and_recover (
1279
+ base, err, kind, ident, spans,
1280
+ ) ;
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1287
+
1288
+ // base case
1289
+ err. help ( & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ) ;
1290
+ err. emit ( ) ;
1291
+
1292
+ Ok ( base)
1293
+ }
1294
+
1295
+ fn prefix_inc_dec_suggest_and_recover (
1296
+ & mut self ,
1297
+ base : P < Expr > ,
1298
+ mut err : DiagnosticBuilder < ' _ > ,
1299
+ kind : IncDecRecovery ,
1300
+ ident : Ident ,
1301
+ ( pre_span, post_span) : ( Span , Span ) ,
1302
+ ) -> PResult < ' a , P < Expr > > {
1303
+ err. multipart_suggestion (
1304
+ & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1305
+ vec ! [
1306
+ ( pre_span, "{ " . to_string( ) ) ,
1307
+ ( post_span, format!( " {}= 1; {} }}" , kind. op. chr( ) , ident) ) ,
1308
+ ] ,
1309
+ Applicability :: MachineApplicable ,
1310
+ ) ;
1311
+ err. emit ( ) ;
1312
+ // TODO: recover
1313
+ Ok ( base)
1314
+ }
1315
+
1316
+ fn postfix_inc_dec_suggest_and_recover (
1317
+ & mut self ,
1318
+ base : P < Expr > ,
1319
+ mut err : DiagnosticBuilder < ' _ > ,
1320
+ kind : IncDecRecovery ,
1321
+ ident : Ident ,
1322
+ ( pre_span, post_span) : ( Span , Span ) ,
1323
+ ) -> PResult < ' a , P < Expr > > {
1324
+ err. multipart_suggestion (
1325
+ & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1326
+ vec ! [
1327
+ ( pre_span, "{ let tmp = " . to_string( ) ) ,
1328
+ ( post_span, format!( "; {} {}= 1; tmp }}" , ident, kind. op. chr( ) ) ) ,
1329
+ ] ,
1330
+ Applicability :: MachineApplicable ,
1331
+ ) ;
1332
+ err. emit ( ) ;
1333
+ // TODO: recover
1334
+ Ok ( base)
1335
+ }
1336
+
1337
+ fn inc_dec_standalone_recovery (
1338
+ & mut self ,
1339
+ base : P < Expr > ,
1340
+ mut err : DiagnosticBuilder < ' _ > ,
1341
+ kind : IncDecRecovery ,
1342
+ _ident : Ident ,
1343
+ ( pre_span, post_span) : ( Span , Span ) ,
1344
+ ) -> PResult < ' a , P < Expr > > {
1345
+ err. multipart_suggestion (
1346
+ & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1347
+ vec ! [ ( pre_span, String :: new( ) ) , ( post_span, format!( " {}= 1" , kind. op. chr( ) ) ) ] ,
1348
+ Applicability :: MachineApplicable ,
1349
+ ) ;
1350
+ err. emit ( ) ;
1351
+ // TODO: recover
1352
+ Ok ( base)
1353
+ }
1354
+
1170
1355
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
1171
1356
/// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
1172
1357
/// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
@@ -1882,49 +2067,6 @@ impl<'a> Parser<'a> {
1882
2067
self . sess . expr_parentheses_needed ( & mut err, * sp) ;
1883
2068
}
1884
2069
err. span_label ( span, "expected expression" ) ;
1885
- if self . prev_token . kind == TokenKind :: BinOp ( token:: Plus )
1886
- && self . token . kind == TokenKind :: BinOp ( token:: Plus )
1887
- && self . look_ahead ( 1 , |t| !t. is_lit ( ) )
1888
- {
1889
- let span = self . prev_token . span . to ( self . token . span ) ;
1890
- err. note ( "Rust has no dedicated increment operator" ) ;
1891
- err. span_suggestion_verbose (
1892
- span,
1893
- "try using `+= 1` instead" ,
1894
- " += 1" . into ( ) ,
1895
- Applicability :: Unspecified ,
1896
- ) ;
1897
- } else if self . token . kind == TokenKind :: BinOp ( token:: Plus )
1898
- && self . look_ahead ( 1 , |t| t. kind == TokenKind :: BinOp ( token:: Plus ) )
1899
- && self . look_ahead ( 2 , |t| !t. is_lit ( ) )
1900
- {
1901
- let target_span = self . look_ahead ( 2 , |t| t. span ) ;
1902
- let left_brace_span = target_span. shrink_to_lo ( ) ;
1903
- let pre_span = self . token . span . to ( self . look_ahead ( 1 , |t| t. span ) ) ;
1904
- let post_span = target_span. shrink_to_hi ( ) ;
1905
-
1906
- err. note ( "Rust has no dedicated increment operator" ) ;
1907
-
1908
- if self . prev_token . kind == TokenKind :: Semi {
1909
- err. multipart_suggestion (
1910
- "try using `+= 1` instead" ,
1911
- vec ! [ ( pre_span, String :: new( ) ) , ( post_span, " += 1" . into( ) ) ] ,
1912
- Applicability :: MachineApplicable ,
1913
- ) ;
1914
- } else if let Ok ( target_snippet) = self . span_to_snippet ( target_span) {
1915
- err. multipart_suggestion (
1916
- "try using `+= 1` instead" ,
1917
- vec ! [
1918
- ( left_brace_span, "{ " . to_string( ) ) ,
1919
- ( pre_span, String :: new( ) ) ,
1920
- ( post_span, format!( " += 1; {} }}" , target_snippet) ) ,
1921
- ] ,
1922
- Applicability :: MachineApplicable ,
1923
- ) ;
1924
- } else {
1925
- err. span_help ( pre_span. to ( target_span) , "try using `+= 1` instead" ) ;
1926
- }
1927
- }
1928
2070
err
1929
2071
}
1930
2072
0 commit comments