11use clippy_utils:: diagnostics:: { span_lint, span_lint_and_then} ;
22use clippy_utils:: trait_ref_of_method;
33use itertools:: Itertools ;
4+ use rustc_ast:: visit:: { try_visit, walk_list} ;
45use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
56use rustc_errors:: Applicability ;
67use rustc_hir:: FnRetTy :: Return ;
@@ -11,8 +12,8 @@ use rustc_hir::intravisit::{
1112} ;
1213use rustc_hir:: {
1314 BareFnTy , BodyId , FnDecl , FnSig , GenericArg , GenericArgs , GenericBound , GenericParam , GenericParamKind , Generics ,
14- Impl , ImplItem , ImplItemKind , Item , ItemKind , Lifetime , LifetimeName , LifetimeParamKind , Node , PolyTraitRef ,
15- PredicateOrigin , TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WherePredicate , lang_items,
15+ HirId , Impl , ImplItem , ImplItemKind , Item , ItemKind , Lifetime , LifetimeName , LifetimeParamKind , Node , PolyTraitRef ,
16+ PredicateOrigin , TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WhereBoundPredicate , WherePredicate , lang_items,
1617} ;
1718use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
1819use rustc_middle:: hir:: map:: Map ;
@@ -483,18 +484,23 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
483484struct Usage {
484485 lifetime : Lifetime ,
485486 in_where_predicate : bool ,
487+ in_bounded_ty : bool ,
486488 in_generics_arg : bool ,
487489}
488490
489491struct LifetimeChecker < ' cx , ' tcx , F > {
490492 cx : & ' cx LateContext < ' tcx > ,
491493 map : FxIndexMap < LocalDefId , Vec < Usage > > ,
492494 where_predicate_depth : usize ,
495+ bounded_ty_depth : usize ,
493496 generic_args_depth : usize ,
494497 phantom : std:: marker:: PhantomData < F > ,
495498}
496499
497- impl < ' cx , ' tcx , F > LifetimeChecker < ' cx , ' tcx , F > {
500+ impl < ' cx , ' tcx , F > LifetimeChecker < ' cx , ' tcx , F >
501+ where
502+ F : NestedFilter < ' tcx > ,
503+ {
498504 fn new ( cx : & ' cx LateContext < ' tcx > , generics : & ' tcx Generics < ' _ > ) -> LifetimeChecker < ' cx , ' tcx , F > {
499505 let map = generics
500506 . params
@@ -510,10 +516,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
510516 cx,
511517 map,
512518 where_predicate_depth : 0 ,
519+ bounded_ty_depth : 0 ,
513520 generic_args_depth : 0 ,
514521 phantom : std:: marker:: PhantomData ,
515522 }
516523 }
524+
525+ // `visit_where_bound_predicate` is based on:
526+ // https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939
527+ fn visit_where_bound_predicate (
528+ & mut self ,
529+ hir_id : HirId ,
530+ bounded_ty : & ' tcx Ty < ' tcx > ,
531+ bounds : & ' tcx [ GenericBound < ' tcx > ] ,
532+ bound_generic_params : & ' tcx [ GenericParam < ' tcx > ] ,
533+ ) {
534+ try_visit ! ( self . visit_id( hir_id) ) ;
535+
536+ self . bounded_ty_depth += 1 ;
537+ try_visit ! ( self . visit_ty( bounded_ty) ) ;
538+ self . bounded_ty_depth -= 1 ;
539+
540+ walk_list ! ( self , visit_param_bound, bounds) ;
541+ walk_list ! ( self , visit_generic_param, bound_generic_params) ;
542+ }
517543}
518544
519545impl < ' tcx , F > Visitor < ' tcx > for LifetimeChecker < ' _ , ' tcx , F >
@@ -531,14 +557,27 @@ where
531557 usages. push ( Usage {
532558 lifetime : * lifetime,
533559 in_where_predicate : self . where_predicate_depth != 0 ,
560+ in_bounded_ty : self . bounded_ty_depth != 0 ,
534561 in_generics_arg : self . generic_args_depth != 0 ,
535562 } ) ;
536563 }
537564 }
538565
539566 fn visit_where_predicate ( & mut self , predicate : & ' tcx WherePredicate < ' tcx > ) {
540567 self . where_predicate_depth += 1 ;
541- walk_where_predicate ( self , predicate) ;
568+ if let & WherePredicate :: BoundPredicate ( WhereBoundPredicate {
569+ hir_id,
570+ bounded_ty,
571+ bounds,
572+ bound_generic_params,
573+ origin : _,
574+ span : _,
575+ } ) = predicate
576+ {
577+ self . visit_where_bound_predicate ( hir_id, bounded_ty, bounds, bound_generic_params) ;
578+ } else {
579+ walk_where_predicate ( self , predicate) ;
580+ }
542581 self . where_predicate_depth -= 1 ;
543582 }
544583
@@ -562,7 +601,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
562601 for ( def_id, usages) in checker. map {
563602 if usages
564603 . iter ( )
565- . all ( |usage| usage. in_where_predicate && !usage. in_generics_arg )
604+ . all ( |usage| usage. in_where_predicate && !usage. in_bounded_ty && !usage . in_generics_arg )
566605 {
567606 span_lint (
568607 cx,
@@ -589,7 +628,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
589628 for ( & def_id, usages) in & checker. map {
590629 if usages
591630 . iter ( )
592- . all ( |usage| usage. in_where_predicate && !usage. in_generics_arg )
631+ . all ( |usage| usage. in_where_predicate && !usage. in_bounded_ty && !usage . in_generics_arg )
593632 {
594633 span_lint (
595634 cx,
@@ -605,8 +644,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
605644
606645// An `impl` lifetime is elidable if it satisfies the following conditions:
607646// - It is used exactly once.
608- // - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
609- // different from `GenericParam`s.)
647+ // - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that
648+ // `GenericArgs` are different from `GenericParam`s.)
610649fn report_elidable_impl_lifetimes < ' tcx > (
611650 cx : & LateContext < ' tcx > ,
612651 impl_ : & ' tcx Impl < ' _ > ,
@@ -623,6 +662,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
623662 }
624663 | Usage {
625664 lifetime,
665+ in_bounded_ty : false ,
626666 in_generics_arg : false ,
627667 ..
628668 } ,
0 commit comments