1
1
use clippy_utils:: diagnostics:: { span_lint, span_lint_and_then} ;
2
2
use clippy_utils:: trait_ref_of_method;
3
3
use itertools:: Itertools ;
4
+ use rustc_ast:: visit:: { try_visit, walk_list} ;
4
5
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
5
6
use rustc_errors:: Applicability ;
6
7
use rustc_hir:: FnRetTy :: Return ;
@@ -11,8 +12,8 @@ use rustc_hir::intravisit::{
11
12
} ;
12
13
use rustc_hir:: {
13
14
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,
16
17
} ;
17
18
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
18
19
use rustc_middle:: hir:: map:: Map ;
@@ -483,18 +484,23 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
483
484
struct Usage {
484
485
lifetime : Lifetime ,
485
486
in_where_predicate : bool ,
487
+ in_bounded_ty : bool ,
486
488
in_generics_arg : bool ,
487
489
}
488
490
489
491
struct LifetimeChecker < ' cx , ' tcx , F > {
490
492
cx : & ' cx LateContext < ' tcx > ,
491
493
map : FxIndexMap < LocalDefId , Vec < Usage > > ,
492
494
where_predicate_depth : usize ,
495
+ bounded_ty_depth : usize ,
493
496
generic_args_depth : usize ,
494
497
phantom : std:: marker:: PhantomData < F > ,
495
498
}
496
499
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
+ {
498
504
fn new ( cx : & ' cx LateContext < ' tcx > , generics : & ' tcx Generics < ' _ > ) -> LifetimeChecker < ' cx , ' tcx , F > {
499
505
let map = generics
500
506
. params
@@ -510,10 +516,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
510
516
cx,
511
517
map,
512
518
where_predicate_depth : 0 ,
519
+ bounded_ty_depth : 0 ,
513
520
generic_args_depth : 0 ,
514
521
phantom : std:: marker:: PhantomData ,
515
522
}
516
523
}
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
+ }
517
543
}
518
544
519
545
impl < ' tcx , F > Visitor < ' tcx > for LifetimeChecker < ' _ , ' tcx , F >
@@ -531,14 +557,27 @@ where
531
557
usages. push ( Usage {
532
558
lifetime : * lifetime,
533
559
in_where_predicate : self . where_predicate_depth != 0 ,
560
+ in_bounded_ty : self . bounded_ty_depth != 0 ,
534
561
in_generics_arg : self . generic_args_depth != 0 ,
535
562
} ) ;
536
563
}
537
564
}
538
565
539
566
fn visit_where_predicate ( & mut self , predicate : & ' tcx WherePredicate < ' tcx > ) {
540
567
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
+ }
542
581
self . where_predicate_depth -= 1 ;
543
582
}
544
583
@@ -562,7 +601,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
562
601
for ( def_id, usages) in checker. map {
563
602
if usages
564
603
. 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 )
566
605
{
567
606
span_lint (
568
607
cx,
@@ -589,7 +628,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
589
628
for ( & def_id, usages) in & checker. map {
590
629
if usages
591
630
. 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 )
593
632
{
594
633
span_lint (
595
634
cx,
@@ -605,8 +644,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
605
644
606
645
// An `impl` lifetime is elidable if it satisfies the following conditions:
607
646
// - 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.)
610
649
fn report_elidable_impl_lifetimes < ' tcx > (
611
650
cx : & LateContext < ' tcx > ,
612
651
impl_ : & ' tcx Impl < ' _ > ,
@@ -623,6 +662,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
623
662
}
624
663
| Usage {
625
664
lifetime,
665
+ in_bounded_ty : false ,
626
666
in_generics_arg : false ,
627
667
..
628
668
} ,
0 commit comments