@@ -26,14 +26,20 @@ use std::collections::BTreeSet;
26
26
27
27
use clippy_utils:: diagnostics:: span_lint;
28
28
use rustc_hir:: intravisit:: FnKind ;
29
- use rustc_hir:: { GenericArg , GenericBound , Generics , Item , ItemKind , WherePredicate } ;
29
+ use rustc_hir:: {
30
+ GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , Item , ItemKind , LifetimeParamKind ,
31
+ WherePredicate ,
32
+ } ;
30
33
use rustc_hir_analysis:: hir_ty_to_ty;
31
34
use rustc_lint:: { LateContext , LateLintPass } ;
32
35
use rustc_middle:: ty:: ty_kind:: TyKind ;
33
36
use rustc_middle:: ty:: { BoundRegionKind , RegionKind , Ty } ;
34
37
use rustc_session:: impl_lint_pass;
35
38
use rustc_span:: Symbol ;
36
39
40
+ extern crate rustc_type_ir;
41
+ use rustc_type_ir:: AliasKind ;
42
+
37
43
declare_clippy_lint ! {
38
44
/// ### What it does
39
45
/// Checks function arguments and return values that have a nested reference type with lifetimes,
@@ -119,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for LifetimesBoundNestedRef {
119
125
let FnKind :: ItemFn ( _ident, generics, _fn_header) = fn_kind else {
120
126
return ;
121
127
} ;
122
- if generics. params . is_empty ( ) {
128
+ if ! at_least_2_explicit_lifetimes ( generics. params ) {
123
129
return ;
124
130
}
125
131
let declared_bounds = get_declared_bounds ( generics) ;
@@ -140,12 +146,12 @@ impl<'tcx> LateLintPass<'tcx> for LifetimesBoundNestedRef {
140
146
let ItemKind :: Impl ( impl_item) = item. kind else {
141
147
return ;
142
148
} ;
143
- if impl_item. generics . params . is_empty ( ) {
144
- return ;
145
- }
146
149
let Some ( of_trait_ref) = impl_item. of_trait else {
147
150
return ;
148
151
} ;
152
+ if !at_least_2_explicit_lifetimes ( impl_item. generics . params ) {
153
+ return ;
154
+ }
149
155
let declared_bounds = get_declared_bounds ( impl_item. generics ) ;
150
156
let mut implied_bounds = BTreeSet :: new ( ) ;
151
157
for path_segment in of_trait_ref. path . segments {
@@ -159,6 +165,8 @@ impl<'tcx> LateLintPass<'tcx> for LifetimesBoundNestedRef {
159
165
}
160
166
}
161
167
}
168
+ let for_clause_ty = hir_ty_to_ty ( cx. tcx , impl_item. self_ty ) ; // impl ... for for_clause_type {}
169
+ collect_nested_ref_implied_bounds ( for_clause_ty, None , & mut implied_bounds) ;
162
170
report_lints ( cx, impl_item. generics . span , & declared_bounds, & implied_bounds) ;
163
171
}
164
172
}
@@ -206,6 +214,19 @@ impl Ord for BoundLftPair {
206
214
}
207
215
}
208
216
217
+ fn at_least_2_explicit_lifetimes < ' a > ( generic_params : & ' a [ GenericParam < ' a > ] ) -> bool {
218
+ generic_params
219
+ . iter ( )
220
+ . filter ( |gp| match gp. kind {
221
+ GenericParamKind :: Lifetime {
222
+ kind : LifetimeParamKind :: Explicit ,
223
+ } => true ,
224
+ _ => false ,
225
+ } )
226
+ . enumerate ( )
227
+ . any ( |( i, _) | i >= 1 )
228
+ }
229
+
209
230
fn get_declared_bounds ( generics : & Generics < ' _ > ) -> BTreeSet < BoundLftPair > {
210
231
let mut declared_bounds = BTreeSet :: new ( ) ;
211
232
for where_predicate in generics. predicates {
@@ -269,6 +290,15 @@ fn collect_nested_ref_implied_bounds(
269
290
TyKind :: Slice ( element_ty) => {
270
291
collect_nested_ref_implied_bounds ( element_ty, outlived_lft_sym_opt, implied_bounds) ;
271
292
} ,
293
+ TyKind :: Alias ( AliasKind :: Projection , alias_ty) => {
294
+ // a for clause in: impl ... for ... {}
295
+ for alias_generic_arg in alias_ty. args {
296
+ let Some ( alias_ty) = alias_generic_arg. as_type ( ) else {
297
+ continue ;
298
+ } ;
299
+ collect_nested_ref_implied_bounds ( alias_ty, outlived_lft_sym_opt, implied_bounds) ;
300
+ }
301
+ } ,
272
302
_ => { } ,
273
303
}
274
304
}
0 commit comments