11use clippy_utils:: diagnostics:: span_lint;
22use clippy_utils:: trait_ref_of_method;
33use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4+ use rustc_hir:: intravisit:: nested_filter:: { self as hir_nested_filter, NestedFilter } ;
45use 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 ,
68} ;
79use rustc_hir:: FnRetTy :: Return ;
810use rustc_hir:: {
9- BareFnTy , BodyId , FnDecl , GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , ImplItem ,
11+ BareFnTy , BodyId , FnDecl , GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , Impl , ImplItem ,
1012 ImplItemKind , Item , ItemKind , LangItem , Lifetime , LifetimeName , ParamName , PolyTraitRef , TraitBoundModifier ,
1113 TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WhereClause , WherePredicate ,
1214} ;
1315use rustc_lint:: { LateContext , LateLintPass } ;
16+ use rustc_middle:: hir:: nested_filter as middle_nested_filter;
1417use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1518use rustc_span:: source_map:: Span ;
1619use rustc_span:: symbol:: { kw, Ident , Symbol } ;
@@ -84,6 +87,8 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
8487 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) {
8588 if let ItemKind :: Fn ( ref sig, ref generics, id) = item. kind {
8689 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_) ;
8792 }
8893 }
8994
@@ -194,8 +199,7 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
194199 visitor. visit_ty( self_ty) ;
195200
196201 !visitor. all_lts( ) . is_empty( )
197- }
198- else {
202+ } else {
199203 false
200204 }
201205 }
@@ -481,11 +485,29 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl
481485 false
482486}
483487
484- struct LifetimeChecker {
488+ struct LifetimeChecker < ' cx , ' tcx , F > {
489+ cx : & ' cx LateContext < ' tcx > ,
485490 map : FxHashMap < Symbol , Span > ,
491+ phantom : std:: marker:: PhantomData < F > ,
486492}
487493
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+
489511 // for lifetimes as parameters of generics
490512 fn visit_lifetime ( & mut self , lifetime : & ' tcx Lifetime ) {
491513 self . map . remove ( & lifetime. name . ident ( ) . name ) ;
@@ -501,6 +523,10 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
501523 walk_generic_param ( self , param) ;
502524 }
503525 }
526+
527+ fn nested_visit_map ( & mut self ) -> Self :: Map {
528+ self . cx . tcx . hir ( )
529+ }
504530}
505531
506532fn 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<'_>,
512538 _ => None ,
513539 } )
514540 . collect ( ) ;
515- let mut checker = LifetimeChecker { map : hs } ;
541+ let mut checker = LifetimeChecker :: < hir_nested_filter :: None > :: new ( cx , hs) ;
516542
517543 walk_generics ( & mut checker, generics) ;
518544 walk_fn_decl ( & mut checker, func) ;
@@ -527,6 +553,32 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
527553 }
528554}
529555
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+
530582struct BodyLifetimeChecker {
531583 lifetimes_used_in_body : bool ,
532584}
0 commit comments