@@ -170,10 +170,12 @@ impl EarlyLintPass for LifetimesBoundNestedRef {
170170 }
171171
172172 /// For issues 84591 and 100051:
173- /// Ignore the supertrait in issue 84591, just check the trait implementation declaration.
174- /// For issue 100051, check the trait implementation declaration, and also check the projection
175- /// impl ... for ... . For these, get declared lifetimes and declared lifetime bounds,
176- /// and compare these with lifetime bounds implied by nested references.
173+ /// Get declared lifetimes and declared lifetime bounds,
174+ /// and compare these with lifetime bounds implied by nested references
175+ /// in a trait implementation declaration.
176+ ///
177+ /// For issue 100051 also check for nested references in the `for` projection: `impl ... for
178+ /// ...` .
177179 fn check_item_post ( & mut self , early_context : & EarlyContext < ' _ > , item : & Item ) {
178180 let ItemKind :: Impl ( box_impl) = & item. kind else {
179181 return ;
@@ -197,22 +199,19 @@ impl EarlyLintPass for LifetimesBoundNestedRef {
197199/// A lifetime bound between a pair of lifetime symbols,
198200/// e.g. 'long: 'outlived.
199201#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord ) ] // use lexicographic ordering
200- struct BoundLftPair {
201- long_lft_sym : Symbol ,
202- outlived_lft_sym : Symbol ,
202+ struct BoundLftSymbolPair {
203+ long_lft : Symbol ,
204+ outlived_lft : Symbol ,
203205}
204206
205- impl BoundLftPair {
206- fn new ( long_lft_sym : Symbol , outlived_lft_sym : Symbol ) -> Self {
207- BoundLftPair {
208- long_lft_sym,
209- outlived_lft_sym,
210- }
207+ impl BoundLftSymbolPair {
208+ fn new ( long_lft : Symbol , outlived_lft : Symbol ) -> Self {
209+ BoundLftSymbolPair { long_lft, outlived_lft }
211210 }
212211
213212 /// A declarion for the lifetimes bound
214213 fn to_declaration ( & self ) -> String {
215- format ! ( "{}: {}" , self . long_lft_sym , self . outlived_lft_sym )
214+ format ! ( "{}: {}" , self . long_lft , self . outlived_lft )
216215 }
217216}
218217
@@ -233,7 +232,7 @@ fn get_declared_lifetimes_spans(generics: &Generics) -> FxHashMap<Symbol, Span>
233232
234233/// From a [Generics] provide a [BTreeMap] of the declared lifetime bounds to the spans of the
235234/// declarations.
236- fn get_declared_bounds_spans ( generics : & Generics ) -> BTreeMap < BoundLftPair , Span > {
235+ fn get_declared_bounds_spans ( generics : & Generics ) -> BTreeMap < BoundLftSymbolPair , Span > {
237236 let mut declared_bounds = BTreeMap :: new ( ) ;
238237 generics. params . iter ( ) . for_each ( |gp| {
239238 let long_lft_sym = gp. ident . name ;
@@ -244,7 +243,10 @@ fn get_declared_bounds_spans(generics: &Generics) -> BTreeMap<BoundLftPair, Span
244243 } else {
245244 outlived_lft. ident . span
246245 } ;
247- declared_bounds. insert ( BoundLftPair :: new ( long_lft_sym, outlived_lft. ident . name ) , decl_span) ;
246+ declared_bounds. insert (
247+ BoundLftSymbolPair :: new ( long_lft_sym, outlived_lft. ident . name ) ,
248+ decl_span,
249+ ) ;
248250 }
249251 } ) ;
250252 } ) ;
@@ -254,7 +256,7 @@ fn get_declared_bounds_spans(generics: &Generics) -> BTreeMap<BoundLftPair, Span
254256 wrp. bounds . iter ( ) . for_each ( |bound| {
255257 if let GenericBound :: Outlives ( outlived_lft) = bound {
256258 // CHECKME: how to make a good span for the lifetimes bound declaration here?
257- declared_bounds. insert ( BoundLftPair :: new ( long_lft_sym, outlived_lft. ident . name ) , wrp. span ) ;
259+ declared_bounds. insert ( BoundLftSymbolPair :: new ( long_lft_sym, outlived_lft. ident . name ) , wrp. span ) ;
258260 }
259261 } ) ;
260262 }
@@ -265,23 +267,28 @@ fn get_declared_bounds_spans(generics: &Generics) -> BTreeMap<BoundLftPair, Span
265267#[ derive( Debug ) ]
266268struct ImpliedBoundsLinter {
267269 declared_lifetimes_spans : FxHashMap < Symbol , Span > ,
268- declared_bounds_spans : BTreeMap < BoundLftPair , Span > ,
269- implied_bounds_spans : BTreeMap < BoundLftPair , ( Span , Span ) > ,
270+ declared_bounds_spans : BTreeMap < BoundLftSymbolPair , Span > ,
271+ /// Map each implied lifetime bound to the spans of the earliest lifetime identifier pair
272+ /// that implies the bound by a nested reference.
273+ implied_bounds_span_pairs : BTreeMap < BoundLftSymbolPair , ( Span , Span ) > ,
270274}
271275
272276impl ImpliedBoundsLinter {
273277 fn new ( declared_lifetimes_spans : FxHashMap < Symbol , Span > , generics : & Generics ) -> Self {
274278 ImpliedBoundsLinter {
275279 declared_lifetimes_spans,
276280 declared_bounds_spans : get_declared_bounds_spans ( generics) ,
277- implied_bounds_spans : BTreeMap :: new ( ) ,
281+ implied_bounds_span_pairs : BTreeMap :: new ( ) ,
278282 }
279283 }
280284
285+ /// Collect implied lifetime bounds span pairs from a complete [Path]
281286 fn collect_implied_lifetime_bounds_path ( & mut self , path : & Path ) {
282287 self . collect_nested_ref_bounds_path ( path, None ) ;
283288 }
284289
290+ /// Collect implied lifetime bounds span pairs from a [Path]
291+ /// that is possibly contained in an outlived lifetime
285292 fn collect_nested_ref_bounds_path ( & mut self , path : & Path , opt_outlived_lft_ident : Option < & Ident > ) {
286293 for path_segment in & path. segments {
287294 if let Some ( generic_args) = & path_segment. args {
@@ -294,7 +301,7 @@ impl ImpliedBoundsLinter {
294301 if let Some ( outlived_lft_ident) = opt_outlived_lft_ident
295302 && self . is_declared_lifetime_sym ( long_lft. ident . name )
296303 {
297- self . add_implied_bound_spans ( & long_lft. ident , outlived_lft_ident) ;
304+ self . add_implied_bound_span_pair ( & long_lft. ident , outlived_lft_ident) ;
298305 }
299306 } ,
300307 GA :: Type ( p_ty) => {
@@ -309,14 +316,17 @@ impl ImpliedBoundsLinter {
309316 }
310317 }
311318
312- fn collect_implied_lifetime_bounds ( & mut self , ty : & Ty ) {
313- self . collect_nested_ref_bounds ( ty, None ) ;
314- }
315-
316319 fn is_declared_lifetime_sym ( & self , lft_sym : Symbol ) -> bool {
317320 self . declared_lifetimes_spans . contains_key ( & lft_sym)
318321 }
319322
323+ /// Collect implied lifetime bounds span pairs from a complete [Ty]
324+ fn collect_implied_lifetime_bounds ( & mut self , ty : & Ty ) {
325+ self . collect_nested_ref_bounds ( ty, None ) ;
326+ }
327+
328+ /// Collect implied lifetime bounds span pairs from a [Ty]
329+ /// that is possibly contained in an outlived lifetime
320330 fn collect_nested_ref_bounds ( & mut self , outliving_ty : & Ty , opt_outlived_lft_ident : Option < & Ident > ) {
321331 let mut outliving_tys = vec ! [ outliving_ty] ; // stack to avoid recursion
322332 while let Some ( ty) = outliving_tys. pop ( ) {
@@ -329,7 +339,7 @@ impl ImpliedBoundsLinter {
329339 && self . is_declared_lifetime_sym ( lifetime. ident . name )
330340 {
331341 if let Some ( outlived_lft_ident) = opt_outlived_lft_ident {
332- self . add_implied_bound_spans ( & lifetime. ident , outlived_lft_ident) ;
342+ self . add_implied_bound_span_pair ( & lifetime. ident , outlived_lft_ident) ;
333343 }
334344 // recursion for nested references outliving this lifetime
335345 self . collect_nested_ref_bounds ( referred_to_ty, Some ( & lifetime. ident ) ) ;
@@ -388,6 +398,8 @@ impl ImpliedBoundsLinter {
388398 }
389399 }
390400
401+ /// Collect implied lifetime bounds span pairs from [GenericBound]s
402+ /// that are possibly contained in an outlived lifetime
391403 fn collect_nested_ref_bounds_gbs (
392404 & mut self ,
393405 generic_bounds : & Vec < GenericBound > ,
@@ -404,7 +416,7 @@ impl ImpliedBoundsLinter {
404416 if let Some ( outlived_lft_ident) = opt_outlived_lft_ident
405417 && self . is_declared_lifetime_sym ( bgp. ident . name )
406418 {
407- self . add_implied_bound_spans ( & bgp. ident , outlived_lft_ident) ;
419+ self . add_implied_bound_span_pair ( & bgp. ident , outlived_lft_ident) ;
408420 }
409421 } ,
410422 GPK :: Type { default : opt_p_ty } => {
@@ -428,22 +440,22 @@ impl ImpliedBoundsLinter {
428440 }
429441 }
430442
431- fn add_implied_bound_spans ( & mut self , long_lft_ident : & Ident , outlived_lft_ident : & Ident ) {
443+ fn add_implied_bound_span_pair ( & mut self , long_lft_ident : & Ident , outlived_lft_ident : & Ident ) {
432444 if long_lft_ident. name == outlived_lft_ident. name {
433445 // only unequal symbols form a lifetime bound
434446 return ;
435447 }
436448 match self
437- . implied_bounds_spans
438- . entry ( BoundLftPair :: new ( long_lft_ident. name , outlived_lft_ident. name ) )
449+ . implied_bounds_span_pairs
450+ . entry ( BoundLftSymbolPair :: new ( long_lft_ident. name , outlived_lft_ident. name ) )
439451 {
440452 Entry :: Vacant ( new_entry) => {
441453 // in nested references the outlived lifetime occurs first
442454 new_entry. insert ( ( outlived_lft_ident. span , long_lft_ident. span ) ) ;
443455 } ,
444456 Entry :: Occupied ( mut prev_entry) => {
445- // keep the first occurrence of the nested reference,
446- // the insertion order here depends on the recursion order.
457+ // keep the first occurring spans for the nested reference.
458+ // ( the actual insertion order here depends on the recursion order)
447459 let prev_spans = prev_entry. get_mut ( ) ;
448460 if ( outlived_lft_ident. span < prev_spans. 0 )
449461 || ( outlived_lft_ident. span == prev_spans. 0 && ( long_lft_ident. span < prev_spans. 1 ) )
@@ -457,11 +469,11 @@ impl ImpliedBoundsLinter {
457469 fn report_lints ( self , cx : & EarlyContext < ' _ > ) {
458470 let bound_implied_here_note = "this lifetimes bound is implied here:" ;
459471
460- for ( implied_bound, ( outlived_lft_span, long_lft_span) ) in & self . implied_bounds_spans {
472+ for ( implied_bound, ( outlived_lft_span, long_lft_span) ) in & self . implied_bounds_span_pairs {
461473 if !self . declared_bounds_spans . contains_key ( implied_bound) {
462474 let impl_bound_decl = implied_bound. to_declaration ( ) ;
463475 let msg_missing = format ! ( "missing lifetimes bound declaration: {impl_bound_decl}" ) ;
464- if let Some ( long_lft_decl_span) = self . declared_lifetimes_spans . get ( & implied_bound. long_lft_sym ) {
476+ if let Some ( long_lft_decl_span) = self . declared_lifetimes_spans . get ( & implied_bound. long_lft ) {
465477 let nested_ref_span = spans_merge ( * outlived_lft_span, * long_lft_span) ;
466478 span_lint_and_fix_sugg_and_note_cause (
467479 cx,
@@ -478,7 +490,7 @@ impl ImpliedBoundsLinter {
478490 }
479491
480492 for ( declared_bound, decl_span) in self . declared_bounds_spans {
481- if let Some ( ( outlived_lft_span, long_lft_span) ) = self . implied_bounds_spans . get ( & declared_bound) {
493+ if let Some ( ( outlived_lft_span, long_lft_span) ) = self . implied_bounds_span_pairs . get ( & declared_bound) {
482494 let nested_ref_span = spans_merge ( * outlived_lft_span, * long_lft_span) ;
483495 span_lint_and_note (
484496 cx,
0 commit comments