@@ -1492,28 +1492,33 @@ impl<'tcx> Liveness<'_, 'tcx> {
1492
1492
) {
1493
1493
// In an or-pattern, only consider the variable; any later patterns must have the same
1494
1494
// bindings, and we also consider the first pattern to be the "authoritative" set of ids.
1495
- // However, we should take the spans of variables with the same name from the later
1495
+ // However, we should take the ids and spans of variables with the same name from the later
1496
1496
// patterns so the suggestions to prefix with underscores will apply to those too.
1497
- let mut vars: FxIndexMap < String , ( LiveNode , Variable , HirId , Vec < Span > ) > = <_ >:: default ( ) ;
1497
+ let mut vars: FxIndexMap < String , ( LiveNode , Variable , Vec < ( HirId , Span ) > ) > = <_ >:: default ( ) ;
1498
1498
1499
1499
pat. each_binding ( |_, hir_id, pat_sp, ident| {
1500
1500
let ln = entry_ln. unwrap_or_else ( || self . live_node ( hir_id, pat_sp) ) ;
1501
1501
let var = self . variable ( hir_id, ident. span ) ;
1502
+ let id_and_sp = ( hir_id, pat_sp) ;
1502
1503
vars. entry ( self . ir . variable_name ( var) )
1503
- . and_modify ( |( .., spans ) | spans . push ( ident . span ) )
1504
- . or_insert_with ( || ( ln, var, hir_id , vec ! [ ident . span ] ) ) ;
1504
+ . and_modify ( |( .., hir_ids_and_spans ) | hir_ids_and_spans . push ( id_and_sp ) )
1505
+ . or_insert_with ( || ( ln, var, vec ! [ id_and_sp ] ) ) ;
1505
1506
} ) ;
1506
1507
1507
- for ( _, ( ln, var, id , spans ) ) in vars {
1508
+ for ( _, ( ln, var, hir_ids_and_spans ) ) in vars {
1508
1509
if self . used_on_entry ( ln, var) {
1510
+ let id = hir_ids_and_spans[ 0 ] . 0 ;
1511
+ let spans = hir_ids_and_spans. into_iter ( ) . map ( |( _, sp) | sp) . collect ( ) ;
1509
1512
on_used_on_entry ( spans, id, ln, var) ;
1510
1513
} else {
1511
- self . report_unused ( spans , id , ln, var) ;
1514
+ self . report_unused ( hir_ids_and_spans , ln, var) ;
1512
1515
}
1513
1516
}
1514
1517
}
1515
1518
1516
- fn report_unused ( & self , spans : Vec < Span > , hir_id : HirId , ln : LiveNode , var : Variable ) {
1519
+ fn report_unused ( & self , hir_ids_and_spans : Vec < ( HirId , Span ) > , ln : LiveNode , var : Variable ) {
1520
+ let first_hir_id = hir_ids_and_spans[ 0 ] . 0 ;
1521
+
1517
1522
if let Some ( name) = self . should_warn ( var) . filter ( |name| name != "self" ) {
1518
1523
// annoying: for parameters in funcs like `fn(x: i32)
1519
1524
// {ret}`, there is only one node, so asking about
@@ -1524,8 +1529,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
1524
1529
if is_assigned {
1525
1530
self . ir . tcx . struct_span_lint_hir (
1526
1531
lint:: builtin:: UNUSED_VARIABLES ,
1527
- hir_id ,
1528
- spans ,
1532
+ first_hir_id ,
1533
+ hir_ids_and_spans . into_iter ( ) . map ( | ( _ , sp ) | sp ) . collect :: < Vec < _ > > ( ) ,
1529
1534
|lint| {
1530
1535
lint. build ( & format ! ( "variable `{}` is assigned to, but never used" , name) )
1531
1536
. note ( & format ! ( "consider using `_{}` instead" , name) )
@@ -1535,31 +1540,49 @@ impl<'tcx> Liveness<'_, 'tcx> {
1535
1540
} else {
1536
1541
self . ir . tcx . struct_span_lint_hir (
1537
1542
lint:: builtin:: UNUSED_VARIABLES ,
1538
- hir_id ,
1539
- spans . clone ( ) ,
1543
+ first_hir_id ,
1544
+ hir_ids_and_spans . iter ( ) . map ( | ( _ , sp ) | * sp ) . collect :: < Vec < _ > > ( ) ,
1540
1545
|lint| {
1541
1546
let mut err = lint. build ( & format ! ( "unused variable: `{}`" , name) ) ;
1542
- if self . ir . variable_is_shorthand ( var) {
1543
- if let Node :: Binding ( pat) = self . ir . tcx . hir ( ) . get ( hir_id) {
1544
- // Handle `ref` and `ref mut`.
1545
- let spans = spans
1546
- . iter ( )
1547
- . map ( |_span| ( pat. span , format ! ( "{}: _" , name) ) )
1548
- . collect ( ) ;
1549
-
1550
- err. multipart_suggestion (
1551
- "try ignoring the field" ,
1552
- spans,
1553
- Applicability :: MachineApplicable ,
1554
- ) ;
1555
- }
1547
+
1548
+ let ( shorthands, non_shorthands) : ( Vec < _ > , Vec < _ > ) =
1549
+ hir_ids_and_spans. into_iter ( ) . partition ( |( hir_id, span) | {
1550
+ let var = self . variable ( * hir_id, * span) ;
1551
+ self . ir . variable_is_shorthand ( var)
1552
+ } ) ;
1553
+
1554
+ let mut shorthands = shorthands
1555
+ . into_iter ( )
1556
+ . map ( |( _, span) | ( span, format ! ( "{}: _" , name) ) )
1557
+ . collect :: < Vec < _ > > ( ) ;
1558
+
1559
+ // If we have both shorthand and non-shorthand, prefer the "try ignoring
1560
+ // the field" message, and suggest `_` for the non-shorthands. If we only
1561
+ // have non-shorthand, then prefix with an underscore instead.
1562
+ if !shorthands. is_empty ( ) {
1563
+ shorthands. extend (
1564
+ non_shorthands
1565
+ . into_iter ( )
1566
+ . map ( |( _, span) | ( span, "_" . to_string ( ) ) )
1567
+ . collect :: < Vec < _ > > ( ) ,
1568
+ ) ;
1569
+
1570
+ err. multipart_suggestion (
1571
+ "try ignoring the field" ,
1572
+ shorthands,
1573
+ Applicability :: MachineApplicable ,
1574
+ ) ;
1556
1575
} else {
1557
1576
err. multipart_suggestion (
1558
1577
"if this is intentional, prefix it with an underscore" ,
1559
- spans. iter ( ) . map ( |span| ( * span, format ! ( "_{}" , name) ) ) . collect ( ) ,
1578
+ non_shorthands
1579
+ . into_iter ( )
1580
+ . map ( |( _, span) | ( span, format ! ( "_{}" , name) ) )
1581
+ . collect :: < Vec < _ > > ( ) ,
1560
1582
Applicability :: MachineApplicable ,
1561
1583
) ;
1562
1584
}
1585
+
1563
1586
err. emit ( )
1564
1587
} ,
1565
1588
) ;
0 commit comments