@@ -98,7 +98,7 @@ use rustc_middle::ty::query::Providers;
98
98
use rustc_middle:: ty:: { self , DefIdTree , RootVariableMinCaptureList , Ty , TyCtxt } ;
99
99
use rustc_session:: lint;
100
100
use rustc_span:: symbol:: { kw, sym, Symbol } ;
101
- use rustc_span:: Span ;
101
+ use rustc_span:: { BytePos , Span } ;
102
102
103
103
use std:: collections:: VecDeque ;
104
104
use std:: io;
@@ -1549,23 +1549,27 @@ impl<'tcx> Liveness<'_, 'tcx> {
1549
1549
. or_insert_with ( || ( ln, var, vec ! [ id_and_sp] ) ) ;
1550
1550
} ) ;
1551
1551
1552
+ let can_remove = matches ! ( & pat. kind, hir:: PatKind :: Struct ( _, _, true ) ) ;
1553
+
1552
1554
for ( _, ( ln, var, hir_ids_and_spans) ) in vars {
1553
1555
if self . used_on_entry ( ln, var) {
1554
1556
let id = hir_ids_and_spans[ 0 ] . 0 ;
1555
1557
let spans =
1556
1558
hir_ids_and_spans. into_iter ( ) . map ( |( _, _, ident_span) | ident_span) . collect ( ) ;
1557
1559
on_used_on_entry ( spans, id, ln, var) ;
1558
1560
} else {
1559
- self . report_unused ( hir_ids_and_spans, ln, var) ;
1561
+ self . report_unused ( hir_ids_and_spans, ln, var, can_remove ) ;
1560
1562
}
1561
1563
}
1562
1564
}
1563
1565
1566
+ #[ tracing:: instrument( skip( self ) , level = "INFO" ) ]
1564
1567
fn report_unused (
1565
1568
& self ,
1566
1569
hir_ids_and_spans : Vec < ( HirId , Span , Span ) > ,
1567
1570
ln : LiveNode ,
1568
1571
var : Variable ,
1572
+ can_remove : bool ,
1569
1573
) {
1570
1574
let first_hir_id = hir_ids_and_spans[ 0 ] . 0 ;
1571
1575
@@ -1590,6 +1594,32 @@ impl<'tcx> Liveness<'_, 'tcx> {
1590
1594
. emit ( ) ;
1591
1595
} ,
1592
1596
)
1597
+ } else if can_remove {
1598
+ self . ir . tcx . struct_span_lint_hir (
1599
+ lint:: builtin:: UNUSED_VARIABLES ,
1600
+ first_hir_id,
1601
+ hir_ids_and_spans. iter ( ) . map ( |( _, pat_span, _) | * pat_span) . collect :: < Vec < _ > > ( ) ,
1602
+ |lint| {
1603
+ let mut err = lint. build ( & format ! ( "unused variable: `{}`" , name) ) ;
1604
+ err. multipart_suggestion (
1605
+ "try removing the field" ,
1606
+ hir_ids_and_spans
1607
+ . iter ( )
1608
+ . map ( |( _, pat_span, _) | {
1609
+ let span = self
1610
+ . ir
1611
+ . tcx
1612
+ . sess
1613
+ . source_map ( )
1614
+ . span_extend_to_next_char ( * pat_span, ',' , true ) ;
1615
+ ( span. with_hi ( BytePos ( span. hi ( ) . 0 + 1 ) ) , String :: new ( ) )
1616
+ } )
1617
+ . collect ( ) ,
1618
+ Applicability :: MachineApplicable ,
1619
+ ) ;
1620
+ err. emit ( ) ;
1621
+ } ,
1622
+ ) ;
1593
1623
} else {
1594
1624
let ( shorthands, non_shorthands) : ( Vec < _ > , Vec < _ > ) =
1595
1625
hir_ids_and_spans. iter ( ) . copied ( ) . partition ( |( hir_id, _, ident_span) | {
0 commit comments