1
1
use clippy_utils:: diagnostics:: span_lint;
2
2
use clippy_utils:: trait_ref_of_method;
3
3
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
+ use rustc_hir:: intravisit:: nested_filter:: { self as hir_nested_filter, NestedFilter } ;
4
5
use rustc_hir:: intravisit:: {
5
- walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty, Visitor ,
6
+ walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
7
+ walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor ,
6
8
} ;
7
9
use rustc_hir:: FnRetTy :: Return ;
8
10
use rustc_hir:: {
9
- BareFnTy , BodyId , FnDecl , GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , ImplItem ,
11
+ BareFnTy , BodyId , FnDecl , GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , Impl , ImplItem ,
10
12
ImplItemKind , Item , ItemKind , LangItem , Lifetime , LifetimeName , ParamName , PolyTraitRef , TraitBoundModifier ,
11
13
TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WhereClause , WherePredicate ,
12
14
} ;
13
15
use rustc_lint:: { LateContext , LateLintPass } ;
16
+ use rustc_middle:: hir:: nested_filter as middle_nested_filter;
14
17
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
15
18
use rustc_span:: source_map:: Span ;
16
19
use rustc_span:: symbol:: { kw, Ident , Symbol } ;
@@ -84,6 +87,8 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
84
87
fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) {
85
88
if let ItemKind :: Fn ( ref sig, ref generics, id) = item. kind {
86
89
check_fn_inner ( cx, sig. decl , Some ( id) , None , generics, item. span , true ) ;
90
+ } else if let ItemKind :: Impl ( ref impl_) = item. kind {
91
+ report_extra_impl_lifetimes ( cx, impl_) ;
87
92
}
88
93
}
89
94
@@ -194,8 +199,7 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
194
199
visitor. visit_ty( self_ty) ;
195
200
196
201
!visitor. all_lts( ) . is_empty( )
197
- }
198
- else {
202
+ } else {
199
203
false
200
204
}
201
205
}
@@ -481,11 +485,29 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl
481
485
false
482
486
}
483
487
484
- struct LifetimeChecker {
488
+ struct LifetimeChecker < ' cx , ' tcx , F > {
489
+ cx : & ' cx LateContext < ' tcx > ,
485
490
map : FxHashMap < Symbol , Span > ,
491
+ phantom : std:: marker:: PhantomData < F > ,
486
492
}
487
493
488
- impl < ' tcx > Visitor < ' tcx > for LifetimeChecker {
494
+ impl < ' cx , ' tcx , F > LifetimeChecker < ' cx , ' tcx , F > {
495
+ fn new ( cx : & ' cx LateContext < ' tcx > , map : FxHashMap < Symbol , Span > ) -> LifetimeChecker < ' cx , ' tcx , F > {
496
+ Self {
497
+ cx,
498
+ map,
499
+ phantom : std:: marker:: PhantomData ,
500
+ }
501
+ }
502
+ }
503
+
504
+ impl < ' cx , ' tcx , F > Visitor < ' tcx > for LifetimeChecker < ' cx , ' tcx , F >
505
+ where
506
+ F : NestedFilter < ' tcx > ,
507
+ {
508
+ type Map = rustc_middle:: hir:: map:: Map < ' tcx > ;
509
+ type NestedFilter = F ;
510
+
489
511
// for lifetimes as parameters of generics
490
512
fn visit_lifetime ( & mut self , lifetime : & ' tcx Lifetime ) {
491
513
self . map . remove ( & lifetime. name . ident ( ) . name ) ;
@@ -501,6 +523,10 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
501
523
walk_generic_param ( self , param) ;
502
524
}
503
525
}
526
+
527
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
528
+ self . cx . tcx . hir ( )
529
+ }
504
530
}
505
531
506
532
fn report_extra_lifetimes < ' tcx > ( cx : & LateContext < ' tcx > , func : & ' tcx FnDecl < ' _ > , generics : & ' tcx Generics < ' _ > ) {
@@ -512,7 +538,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
512
538
_ => None ,
513
539
} )
514
540
. collect ( ) ;
515
- let mut checker = LifetimeChecker { map : hs } ;
541
+ let mut checker = LifetimeChecker :: < hir_nested_filter :: None > :: new ( cx , hs) ;
516
542
517
543
walk_generics ( & mut checker, generics) ;
518
544
walk_fn_decl ( & mut checker, func) ;
@@ -527,6 +553,32 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
527
553
}
528
554
}
529
555
556
+ fn report_extra_impl_lifetimes < ' tcx > ( cx : & LateContext < ' tcx > , impl_ : & ' tcx Impl < ' _ > ) {
557
+ let hs = impl_
558
+ . generics
559
+ . params
560
+ . iter ( )
561
+ . filter_map ( |par| match par. kind {
562
+ GenericParamKind :: Lifetime { .. } => Some ( ( par. name . ident ( ) . name , par. span ) ) ,
563
+ _ => None ,
564
+ } )
565
+ . collect ( ) ;
566
+ let mut checker = LifetimeChecker :: < middle_nested_filter:: All > :: new ( cx, hs) ;
567
+
568
+ walk_generics ( & mut checker, & impl_. generics ) ;
569
+ if let Some ( ref trait_ref) = impl_. of_trait {
570
+ walk_trait_ref ( & mut checker, trait_ref) ;
571
+ }
572
+ walk_ty ( & mut checker, impl_. self_ty ) ;
573
+ for item in impl_. items {
574
+ walk_impl_item_ref ( & mut checker, item) ;
575
+ }
576
+
577
+ for & v in checker. map . values ( ) {
578
+ span_lint ( cx, EXTRA_UNUSED_LIFETIMES , v, "this lifetime isn't used in the impl" ) ;
579
+ }
580
+ }
581
+
530
582
struct BodyLifetimeChecker {
531
583
lifetimes_used_in_body : bool ,
532
584
}
0 commit comments