@@ -85,7 +85,7 @@ use self::LiveNodeKind::*;
85
85
use self :: VarKind :: * ;
86
86
87
87
use rustc_ast:: InlineAsmOptions ;
88
- use rustc_data_structures:: fx:: FxIndexMap ;
88
+ use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
89
89
use rustc_errors:: Applicability ;
90
90
use rustc_hir as hir;
91
91
use rustc_hir:: def:: * ;
@@ -99,6 +99,7 @@ use rustc_session::lint;
99
99
use rustc_span:: symbol:: { kw, sym, Symbol } ;
100
100
use rustc_span:: { BytePos , Span } ;
101
101
102
+ use std:: cell:: RefCell ;
102
103
use std:: collections:: VecDeque ;
103
104
use std:: io;
104
105
use std:: io:: prelude:: * ;
@@ -138,9 +139,9 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
138
139
}
139
140
}
140
141
141
- fn check_liveness ( tcx : TyCtxt < ' _ > , def_id : DefId ) {
142
+ fn check_liveness ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Option < FxIndexSet < Span > > {
142
143
let local_def_id = match def_id. as_local ( ) {
143
- None => return ,
144
+ None => return None ,
144
145
Some ( def_id) => def_id,
145
146
} ;
146
147
@@ -149,12 +150,12 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
149
150
if let DefKind :: Impl = tcx. def_kind ( parent)
150
151
&& tcx. has_attr ( parent. to_def_id ( ) , sym:: automatically_derived)
151
152
{
152
- return ;
153
+ return None ;
153
154
}
154
155
155
156
// Don't run unused pass for #[naked]
156
157
if tcx. has_attr ( def_id, sym:: naked) {
157
- return ;
158
+ return None ;
158
159
}
159
160
160
161
let mut maps = IrMaps :: new ( tcx) ;
@@ -182,6 +183,8 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
182
183
lsets. visit_body ( body) ;
183
184
lsets. warn_about_unused_upvars ( entry_ln) ;
184
185
lsets. warn_about_unused_args ( body, entry_ln) ;
186
+
187
+ Some ( lsets. unused_variables_spans . into_inner ( ) )
185
188
}
186
189
187
190
pub fn provide ( providers : & mut Providers ) {
@@ -517,6 +520,8 @@ struct Liveness<'a, 'tcx> {
517
520
// it probably doesn't now)
518
521
break_ln : HirIdMap < LiveNode > ,
519
522
cont_ln : HirIdMap < LiveNode > ,
523
+
524
+ unused_variables_spans : RefCell < FxIndexSet < Span > > ,
520
525
}
521
526
522
527
impl < ' a , ' tcx > Liveness < ' a , ' tcx > {
@@ -541,6 +546,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
541
546
exit_ln,
542
547
break_ln : Default :: default ( ) ,
543
548
cont_ln : Default :: default ( ) ,
549
+ unused_variables_spans : Default :: default ( ) ,
544
550
}
545
551
}
546
552
@@ -1504,6 +1510,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
1504
1510
}
1505
1511
} else {
1506
1512
if let Some ( name) = self . should_warn ( var) {
1513
+ self . unused_variables_spans . borrow_mut ( ) . insert ( span) ;
1507
1514
self . ir . tcx . struct_span_lint_hir (
1508
1515
lint:: builtin:: UNUSED_VARIABLES ,
1509
1516
var_hir_id,
@@ -1594,24 +1601,29 @@ impl<'tcx> Liveness<'_, 'tcx> {
1594
1601
if ln == self . exit_ln { false } else { self . assigned_on_exit ( ln, var) } ;
1595
1602
1596
1603
if is_assigned {
1604
+ let spans = hir_ids_and_spans
1605
+ . into_iter ( )
1606
+ . map ( |( _, _, ident_span) | ident_span)
1607
+ . collect :: < Vec < _ > > ( ) ;
1608
+ self . unused_variables_spans . borrow_mut ( ) . extend ( & spans) ;
1597
1609
self . ir . tcx . struct_span_lint_hir (
1598
1610
lint:: builtin:: UNUSED_VARIABLES ,
1599
1611
first_hir_id,
1600
- hir_ids_and_spans
1601
- . into_iter ( )
1602
- . map ( |( _, _, ident_span) | ident_span)
1603
- . collect :: < Vec < _ > > ( ) ,
1612
+ spans,
1604
1613
|lint| {
1605
1614
lint. build ( & format ! ( "variable `{}` is assigned to, but never used" , name) )
1606
1615
. note ( & format ! ( "consider using `_{}` instead" , name) )
1607
1616
. emit ( ) ;
1608
1617
} ,
1609
1618
)
1610
1619
} else if can_remove {
1620
+ let spans =
1621
+ hir_ids_and_spans. iter ( ) . map ( |( _, pat_span, _) | * pat_span) . collect :: < Vec < _ > > ( ) ;
1622
+ self . unused_variables_spans . borrow_mut ( ) . extend ( & spans) ;
1611
1623
self . ir . tcx . struct_span_lint_hir (
1612
1624
lint:: builtin:: UNUSED_VARIABLES ,
1613
1625
first_hir_id,
1614
- hir_ids_and_spans . iter ( ) . map ( | ( _ , pat_span , _ ) | * pat_span ) . collect :: < Vec < _ > > ( ) ,
1626
+ spans ,
1615
1627
|lint| {
1616
1628
let mut err = lint. build ( & format ! ( "unused variable: `{}`" , name) ) ;
1617
1629
err. multipart_suggestion (
@@ -1654,13 +1666,15 @@ impl<'tcx> Liveness<'_, 'tcx> {
1654
1666
)
1655
1667
. collect :: < Vec < _ > > ( ) ;
1656
1668
1669
+ let spans = hir_ids_and_spans
1670
+ . iter ( )
1671
+ . map ( |( _, pat_span, _) | * pat_span)
1672
+ . collect :: < Vec < _ > > ( ) ;
1673
+ self . unused_variables_spans . borrow_mut ( ) . extend ( & spans) ;
1657
1674
self . ir . tcx . struct_span_lint_hir (
1658
1675
lint:: builtin:: UNUSED_VARIABLES ,
1659
1676
first_hir_id,
1660
- hir_ids_and_spans
1661
- . iter ( )
1662
- . map ( |( _, pat_span, _) | * pat_span)
1663
- . collect :: < Vec < _ > > ( ) ,
1677
+ spans,
1664
1678
|lint| {
1665
1679
let mut err = lint. build ( & format ! ( "unused variable: `{}`" , name) ) ;
1666
1680
err. multipart_suggestion (
@@ -1677,13 +1691,15 @@ impl<'tcx> Liveness<'_, 'tcx> {
1677
1691
. map ( |( _, _, ident_span) | ( ident_span, format ! ( "_{}" , name) ) )
1678
1692
. collect :: < Vec < _ > > ( ) ;
1679
1693
1694
+ let spans = hir_ids_and_spans
1695
+ . iter ( )
1696
+ . map ( |( _, _, ident_span) | * ident_span)
1697
+ . collect :: < Vec < _ > > ( ) ;
1698
+ self . unused_variables_spans . borrow_mut ( ) . extend ( & spans) ;
1680
1699
self . ir . tcx . struct_span_lint_hir (
1681
1700
lint:: builtin:: UNUSED_VARIABLES ,
1682
1701
first_hir_id,
1683
- hir_ids_and_spans
1684
- . iter ( )
1685
- . map ( |( _, _, ident_span) | * ident_span)
1686
- . collect :: < Vec < _ > > ( ) ,
1702
+ spans,
1687
1703
|lint| {
1688
1704
let mut err = lint. build ( & format ! ( "unused variable: `{}`" , name) ) ;
1689
1705
if self . has_added_lit_match_name_span ( & name, opt_body, & mut err) {
0 commit comments