@@ -218,6 +218,27 @@ impl std::fmt::Display for UnaryFixity {
218
218
}
219
219
}
220
220
221
+ struct MultiSugg {
222
+ msg : String ,
223
+ patches : Vec < ( Span , String ) > ,
224
+ applicability : Applicability ,
225
+ }
226
+
227
+ impl MultiSugg {
228
+ fn emit ( self , err : & mut DiagnosticBuilder < ' _ > ) {
229
+ err. multipart_suggestion ( & self . msg , self . patches , self . applicability ) ;
230
+ }
231
+
232
+ /// Overrides individual messages and applicabilities.
233
+ fn emit_many (
234
+ err : & mut DiagnosticBuilder < ' _ > ,
235
+ msg : & str ,
236
+ applicability : Applicability ,
237
+ suggestions : impl Iterator < Item = Self > ,
238
+ ) {
239
+ err. multipart_suggestions ( msg, suggestions. map ( |s| s. patches ) , applicability) ;
240
+ }
241
+ }
221
242
// SnapshotParser is used to create a snapshot of the parser
222
243
// without causing duplicate errors being emitted when the `Parser`
223
244
// is dropped.
@@ -1281,33 +1302,33 @@ impl<'a> Parser<'a> {
1281
1302
} ;
1282
1303
1283
1304
match kind. standalone {
1284
- IsStandalone :: Standalone => {
1285
- self . inc_dec_standalone_recovery ( & mut err, kind, spans, false )
1286
- }
1305
+ IsStandalone :: Standalone => self . inc_dec_standalone_suggest ( kind, spans) . emit ( & mut err) ,
1287
1306
IsStandalone :: Subexpr => {
1288
1307
let Ok ( base_src) = self . span_to_snippet ( base. span )
1289
1308
else { return help_base_case ( err, base) } ;
1290
1309
match kind. fixity {
1291
1310
UnaryFixity :: Pre => {
1292
- self . prefix_inc_dec_suggest ( base_src, & mut err , kind, spans)
1311
+ self . prefix_inc_dec_suggest ( base_src, kind, spans) . emit ( & mut err )
1293
1312
}
1294
1313
UnaryFixity :: Post => {
1295
- self . postfix_inc_dec_suggest ( base_src, & mut err , kind, spans)
1314
+ self . postfix_inc_dec_suggest ( base_src, kind, spans) . emit ( & mut err )
1296
1315
}
1297
1316
}
1298
1317
}
1299
1318
IsStandalone :: Maybe => {
1300
1319
let Ok ( base_src) = self . span_to_snippet ( base. span )
1301
1320
else { return help_base_case ( err, base) } ;
1302
- match kind. fixity {
1303
- UnaryFixity :: Pre => {
1304
- self . prefix_inc_dec_suggest ( base_src, & mut err, kind, spans)
1305
- }
1306
- UnaryFixity :: Post => {
1307
- self . postfix_inc_dec_suggest ( base_src, & mut err, kind, spans)
1308
- }
1309
- }
1310
- self . inc_dec_standalone_recovery ( & mut err, kind, spans, true )
1321
+ let sugg1 = match kind. fixity {
1322
+ UnaryFixity :: Pre => self . prefix_inc_dec_suggest ( base_src, kind, spans) ,
1323
+ UnaryFixity :: Post => self . postfix_inc_dec_suggest ( base_src, kind, spans) ,
1324
+ } ;
1325
+ let sugg2 = self . inc_dec_standalone_suggest ( kind, spans) ;
1326
+ MultiSugg :: emit_many (
1327
+ & mut err,
1328
+ "use `+= 1` instead" ,
1329
+ Applicability :: MaybeIncorrect ,
1330
+ [ sugg1, sugg2] . into_iter ( ) ,
1331
+ )
1311
1332
}
1312
1333
}
1313
1334
Err ( err)
@@ -1316,61 +1337,46 @@ impl<'a> Parser<'a> {
1316
1337
fn prefix_inc_dec_suggest (
1317
1338
& mut self ,
1318
1339
base_src : String ,
1319
- err : & mut DiagnosticBuilder < ' a > ,
1320
1340
kind : IncDecRecovery ,
1321
1341
( pre_span, post_span) : ( Span , Span ) ,
1322
- ) {
1323
- err . multipart_suggestion (
1324
- & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1325
- vec ! [
1342
+ ) -> MultiSugg {
1343
+ MultiSugg {
1344
+ msg : format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1345
+ patches : vec ! [
1326
1346
( pre_span, "{ " . to_string( ) ) ,
1327
1347
( post_span, format!( " {}= 1; {} }}" , kind. op. chr( ) , base_src) ) ,
1328
1348
] ,
1329
- Applicability :: MachineApplicable ,
1330
- ) ;
1349
+ applicability : Applicability :: MachineApplicable ,
1350
+ }
1331
1351
}
1332
1352
1333
1353
fn postfix_inc_dec_suggest (
1334
1354
& mut self ,
1335
1355
base_src : String ,
1336
- err : & mut DiagnosticBuilder < ' a > ,
1337
1356
kind : IncDecRecovery ,
1338
1357
( pre_span, post_span) : ( Span , Span ) ,
1339
- ) {
1358
+ ) -> MultiSugg {
1340
1359
let tmp_var = if base_src. trim ( ) == "tmp" { "tmp_" } else { "tmp" } ;
1341
- err . multipart_suggestion (
1342
- & format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1343
- vec ! [
1360
+ MultiSugg {
1361
+ msg : format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1362
+ patches : vec ! [
1344
1363
( pre_span, format!( "{{ let {} = " , tmp_var) ) ,
1345
1364
( post_span, format!( "; {} {}= 1; {} }}" , base_src, kind. op. chr( ) , tmp_var) ) ,
1346
1365
] ,
1347
- Applicability :: HasPlaceholders ,
1348
- ) ;
1366
+ applicability : Applicability :: HasPlaceholders ,
1367
+ }
1349
1368
}
1350
1369
1351
- fn inc_dec_standalone_recovery (
1370
+ fn inc_dec_standalone_suggest (
1352
1371
& mut self ,
1353
- err : & mut DiagnosticBuilder < ' a > ,
1354
1372
kind : IncDecRecovery ,
1355
1373
( pre_span, post_span) : ( Span , Span ) ,
1356
- maybe_not_standalone : bool ,
1357
- ) {
1358
- let msg = if maybe_not_standalone {
1359
- "or, if you don't need to use it as an expression, change it to this" . to_owned ( )
1360
- } else {
1361
- format ! ( "use `{}= 1` instead" , kind. op. chr( ) )
1362
- } ;
1363
- let applicability = if maybe_not_standalone {
1364
- // FIXME: Unspecified isn't right, but it's the least wrong option
1365
- Applicability :: Unspecified
1366
- } else {
1367
- Applicability :: MachineApplicable
1368
- } ;
1369
- err. multipart_suggestion (
1370
- & msg,
1371
- vec ! [ ( pre_span, String :: new( ) ) , ( post_span, format!( " {}= 1" , kind. op. chr( ) ) ) ] ,
1372
- applicability,
1373
- ) ;
1374
+ ) -> MultiSugg {
1375
+ MultiSugg {
1376
+ msg : format ! ( "use `{}= 1` instead" , kind. op. chr( ) ) ,
1377
+ patches : vec ! [ ( pre_span, String :: new( ) ) , ( post_span, format!( " {}= 1" , kind. op. chr( ) ) ) ] ,
1378
+ applicability : Applicability :: MachineApplicable ,
1379
+ }
1374
1380
}
1375
1381
1376
1382
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
0 commit comments