@@ -9,12 +9,14 @@ use rustc_hir::intravisit::{
9
9
use rustc_hir:: FnRetTy :: Return ;
10
10
use rustc_hir:: {
11
11
BareFnTy , BodyId , FnDecl , GenericArg , GenericBound , GenericParam , GenericParamKind , Generics , Impl , ImplItem ,
12
- ImplItemKind , Item , ItemKind , LangItem , Lifetime , LifetimeName , LifetimeParamKind , ParamName , PolyTraitRef ,
13
- PredicateOrigin , TraitBoundModifier , TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WherePredicate ,
12
+ ImplItemKind , Item , ItemKind , LangItem , Lifetime , LifetimeName , ParamName , PolyTraitRef , PredicateOrigin ,
13
+ TraitBoundModifier , TraitFn , TraitItem , TraitItemKind , Ty , TyKind , WherePredicate ,
14
14
} ;
15
15
use rustc_lint:: { LateContext , LateLintPass } ;
16
16
use rustc_middle:: hir:: nested_filter as middle_nested_filter;
17
+ use rustc_middle:: ty:: TyCtxt ;
17
18
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
19
+ use rustc_span:: def_id:: LocalDefId ;
18
20
use rustc_span:: source_map:: Span ;
19
21
use rustc_span:: symbol:: { kw, Ident , Symbol } ;
20
22
@@ -129,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
129
131
enum RefLt {
130
132
Unnamed ,
131
133
Static ,
132
- Named ( Symbol ) ,
134
+ Named ( LocalDefId ) ,
133
135
}
134
136
135
137
fn check_fn_inner < ' tcx > (
@@ -232,7 +234,7 @@ fn could_use_elision<'tcx>(
232
234
// level of the current item.
233
235
234
236
// check named LTs
235
- let allowed_lts = allowed_lts_from ( named_generics) ;
237
+ let allowed_lts = allowed_lts_from ( cx . tcx , named_generics) ;
236
238
237
239
// these will collect all the lifetimes for references in arg/return types
238
240
let mut input_visitor = RefVisitor :: new ( cx) ;
@@ -254,22 +256,6 @@ fn could_use_elision<'tcx>(
254
256
return false ;
255
257
}
256
258
257
- if allowed_lts
258
- . intersection (
259
- & input_visitor
260
- . nested_elision_site_lts
261
- . iter ( )
262
- . chain ( output_visitor. nested_elision_site_lts . iter ( ) )
263
- . cloned ( )
264
- . filter ( |v| matches ! ( v, RefLt :: Named ( _) ) )
265
- . collect ( ) ,
266
- )
267
- . next ( )
268
- . is_some ( )
269
- {
270
- return false ;
271
- }
272
-
273
259
let input_lts = input_visitor. lts ;
274
260
let output_lts = output_visitor. lts ;
275
261
@@ -303,6 +289,31 @@ fn could_use_elision<'tcx>(
303
289
}
304
290
}
305
291
292
+ // check for higher-ranked trait bounds
293
+ if !input_visitor. nested_elision_site_lts . is_empty ( ) || !output_visitor. nested_elision_site_lts . is_empty ( ) {
294
+ let allowed_lts: FxHashSet < _ > = allowed_lts
295
+ . iter ( )
296
+ . filter_map ( |lt| match lt {
297
+ RefLt :: Named ( def_id) => Some ( cx. tcx . item_name ( def_id. to_def_id ( ) ) ) ,
298
+ _ => None ,
299
+ } )
300
+ . collect ( ) ;
301
+ for lt in input_visitor. nested_elision_site_lts {
302
+ if let RefLt :: Named ( def_id) = lt {
303
+ if allowed_lts. contains ( & cx. tcx . item_name ( def_id. to_def_id ( ) ) ) {
304
+ return false ;
305
+ }
306
+ }
307
+ }
308
+ for lt in output_visitor. nested_elision_site_lts {
309
+ if let RefLt :: Named ( def_id) = lt {
310
+ if allowed_lts. contains ( & cx. tcx . item_name ( def_id. to_def_id ( ) ) ) {
311
+ return false ;
312
+ }
313
+ }
314
+ }
315
+ }
316
+
306
317
// no input lifetimes? easy case!
307
318
if input_lts. is_empty ( ) {
308
319
false
@@ -335,14 +346,11 @@ fn could_use_elision<'tcx>(
335
346
}
336
347
}
337
348
338
- fn allowed_lts_from ( named_generics : & [ GenericParam < ' _ > ] ) -> FxHashSet < RefLt > {
349
+ fn allowed_lts_from ( tcx : TyCtxt < ' _ > , named_generics : & [ GenericParam < ' _ > ] ) -> FxHashSet < RefLt > {
339
350
let mut allowed_lts = FxHashSet :: default ( ) ;
340
351
for par in named_generics. iter ( ) {
341
- if let GenericParamKind :: Lifetime {
342
- kind : LifetimeParamKind :: Explicit ,
343
- } = par. kind
344
- {
345
- allowed_lts. insert ( RefLt :: Named ( par. name . ident ( ) . name ) ) ;
352
+ if let GenericParamKind :: Lifetime { .. } = par. kind {
353
+ allowed_lts. insert ( RefLt :: Named ( tcx. hir ( ) . local_def_id ( par. hir_id ) ) ) ;
346
354
}
347
355
}
348
356
allowed_lts. insert ( RefLt :: Unnamed ) ;
@@ -385,8 +393,10 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
385
393
self . lts . push ( RefLt :: Unnamed ) ;
386
394
} else if lt. is_elided ( ) {
387
395
self . lts . push ( RefLt :: Unnamed ) ;
396
+ } else if let LifetimeName :: Param ( def_id, _) = lt. name {
397
+ self . lts . push ( RefLt :: Named ( def_id) ) ;
388
398
} else {
389
- self . lts . push ( RefLt :: Named ( lt . name . ident ( ) . name ) ) ;
399
+ self . lts . push ( RefLt :: Unnamed ) ;
390
400
}
391
401
} else {
392
402
self . lts . push ( RefLt :: Unnamed ) ;
@@ -434,10 +444,15 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
434
444
TyKind :: OpaqueDef ( item, bounds) => {
435
445
let map = self . cx . tcx . hir ( ) ;
436
446
let item = map. item ( item) ;
447
+ let len = self . lts . len ( ) ;
437
448
walk_item ( self , item) ;
438
- walk_ty ( self , ty ) ;
449
+ self . lts . truncate ( len ) ;
439
450
self . lts . extend ( bounds. iter ( ) . filter_map ( |bound| match bound {
440
- GenericArg :: Lifetime ( l) => Some ( RefLt :: Named ( l. name . ident ( ) . name ) ) ,
451
+ GenericArg :: Lifetime ( l) => Some ( if let LifetimeName :: Param ( def_id, _) = l. name {
452
+ RefLt :: Named ( def_id)
453
+ } else {
454
+ RefLt :: Unnamed
455
+ } ) ,
441
456
_ => None ,
442
457
} ) ) ;
443
458
} ,
@@ -456,9 +471,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
456
471
}
457
472
return ;
458
473
} ,
459
- _ => ( ) ,
474
+ _ => walk_ty ( self , ty ) ,
460
475
}
461
- walk_ty ( self , ty) ;
462
476
}
463
477
}
464
478
@@ -477,7 +491,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
477
491
return true ;
478
492
}
479
493
// if the bounds define new lifetimes, they are fine to occur
480
- let allowed_lts = allowed_lts_from ( pred. bound_generic_params ) ;
494
+ let allowed_lts = allowed_lts_from ( cx . tcx , pred. bound_generic_params ) ;
481
495
// now walk the bounds
482
496
for bound in pred. bounds . iter ( ) {
483
497
walk_param_bound ( & mut visitor, bound) ;
0 commit comments