@@ -31,6 +31,7 @@ use syntax_pos::Span;
3131use  errors:: DiagnosticBuilder ; 
3232use  util:: nodemap:: { DefIdMap ,  FxHashMap ,  FxHashSet ,  NodeMap ,  NodeSet } ; 
3333use  std:: slice; 
34+ use  rustc:: lint; 
3435
3536use  hir; 
3637use  hir:: intravisit:: { self ,  NestedVisitorMap ,  Visitor } ; 
@@ -56,6 +57,13 @@ impl LifetimeDefOrigin {
5657    } 
5758} 
5859
60+ // This counts the no of times a lifetime is used 
61+ #[ derive( Clone ,  Copy ,  Debug ) ]  
62+ pub  enum  LifetimeUseSet < ' tcx >  { 
63+     One ( & ' tcx  hir:: Lifetime ) , 
64+     Many , 
65+ } 
66+ 
5967#[ derive( Clone ,  Copy ,  PartialEq ,  Eq ,  Hash ,  RustcEncodable ,  RustcDecodable ,  Debug ) ]  
6068pub  enum  Region  { 
6169    Static , 
@@ -245,6 +253,8 @@ struct LifetimeContext<'a, 'tcx: 'a> {
245253
246254    // Cache for cross-crate per-definition object lifetime defaults. 
247255    xcrate_object_lifetime_defaults :  DefIdMap < Vec < ObjectLifetimeDefault > > , 
256+ 
257+     lifetime_uses :  DefIdMap < LifetimeUseSet < ' tcx > > , 
248258} 
249259
250260#[ derive( Debug ) ]  
@@ -407,6 +417,7 @@ fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
407417            is_in_fn_syntax :  false , 
408418            labels_in_fn :  vec ! [ ] , 
409419            xcrate_object_lifetime_defaults :  DefIdMap ( ) , 
420+             lifetime_uses :  DefIdMap ( ) , 
410421        } ; 
411422        for  ( _,  item)  in  & krate. items  { 
412423            visitor. visit_item ( item) ; 
@@ -443,8 +454,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
443454    fn  visit_item ( & mut  self ,  item :  & ' tcx  hir:: Item )  { 
444455        match  item. node  { 
445456            hir:: ItemFn ( ref  decl,  _,  _,  _,  ref  generics,  _)  => { 
446-                 self . visit_early_late ( None ,  decl,  generics,  |this| { 
447-                     intravisit:: walk_item ( this,  item) ; 
457+                 self . visit_early_late ( None , 
458+                                       decl, 
459+                                       generics, 
460+                                       |this| { 
461+                                           intravisit:: walk_item ( this,  item) ; 
448462                } ) ; 
449463            } 
450464            hir:: ItemExternCrate ( _) 
@@ -499,9 +513,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
499513    fn  visit_foreign_item ( & mut  self ,  item :  & ' tcx  hir:: ForeignItem )  { 
500514        match  item. node  { 
501515            hir:: ForeignItemFn ( ref  decl,  _,  ref  generics)  => { 
502-                 self . visit_early_late ( None ,  decl,  generics,  |this| { 
503-                     intravisit:: walk_foreign_item ( this,  item) ; 
504-                 } ) 
516+                 self . visit_early_late ( None , 
517+                                       decl, 
518+                                       generics, 
519+                                       |this| { 
520+                                           intravisit:: walk_foreign_item ( this,  item) ; 
521+                                       } ) 
505522            } 
506523            hir:: ForeignItemStatic ( ..)  => { 
507524                intravisit:: walk_foreign_item ( self ,  item) ; 
@@ -1190,12 +1207,41 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
11901207            is_in_fn_syntax :  self . is_in_fn_syntax , 
11911208            labels_in_fn, 
11921209            xcrate_object_lifetime_defaults, 
1210+             lifetime_uses :  DefIdMap ( ) , 
11931211        } ; 
11941212        debug ! ( "entering scope {:?}" ,  this. scope) ; 
11951213        f ( self . scope ,  & mut  this) ; 
11961214        debug ! ( "exiting scope {:?}" ,  this. scope) ; 
11971215        self . labels_in_fn  = this. labels_in_fn ; 
11981216        self . xcrate_object_lifetime_defaults  = this. xcrate_object_lifetime_defaults ; 
1217+ 
1218+         for  ( def_id,  lifetimeuseset)  in  & this. lifetime_uses  { 
1219+             match  lifetimeuseset { 
1220+                 & LifetimeUseSet :: One ( _)  => { 
1221+                     let  node_id = this. tcx . hir . as_local_node_id ( * def_id) . unwrap ( ) ; 
1222+                     debug ! ( "node id first={:?}" ,  node_id) ; 
1223+                     if  let  hir:: map:: NodeLifetime ( hir_lifetime)  = this. tcx . hir . get ( node_id)  { 
1224+                         let  span = hir_lifetime. span ; 
1225+                         let  id = hir_lifetime. id ; 
1226+                         debug ! ( "id ={:?} span = {:?} hir_lifetime = {:?}" , 
1227+                             node_id, 
1228+                             span, 
1229+                             hir_lifetime) ; 
1230+ 
1231+                         this. tcx 
1232+                             . struct_span_lint_node ( lint:: builtin:: SINGLE_USE_LIFETIME , 
1233+                                                    id, 
1234+                                                    span, 
1235+                                                    & format ! ( "lifetime name `{}` only used once" , 
1236+                                                    hir_lifetime. name. name( ) ) ) 
1237+                             . emit ( ) ; 
1238+                     } 
1239+                 } 
1240+                 _ => { 
1241+                     debug ! ( "Not one use lifetime" ) ; 
1242+                 } 
1243+             } 
1244+         } 
11991245    } 
12001246
12011247    /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. 
@@ -1287,9 +1333,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
12871333        } 
12881334    } 
12891335
1290-     fn  resolve_lifetime_ref ( & mut  self ,  lifetime_ref :  & hir:: Lifetime )  { 
1336+     fn  resolve_lifetime_ref ( & mut  self ,  lifetime_ref :  & ' tcx   hir:: Lifetime )  { 
12911337        debug ! ( "resolve_lifetime_ref(lifetime_ref={:?})" ,  lifetime_ref) ; 
1292- 
12931338        // Walk up the scope chain, tracking the number of fn scopes 
12941339        // that we pass through, until we find a lifetime with the 
12951340        // given name or we run out of scopes. 
@@ -1581,8 +1626,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15811626            } 
15821627
15831628            // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). 
1584-             hir:: map:: NodeForeignItem ( _)  | hir:: map:: NodeTy ( _)  | hir:: map:: NodeTraitRef ( _)  =>  None , 
1585- 
1629+             hir:: map:: NodeForeignItem ( _)  | hir:: map:: NodeTy ( _)  | hir:: map:: NodeTraitRef ( _)  =>
1630+                  None , 
15861631            // Everything else (only closures?) doesn't 
15871632            // actually enjoy elision in return types. 
15881633            _ => { 
@@ -1758,7 +1803,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
17581803        } 
17591804    } 
17601805
1761-     fn  resolve_elided_lifetimes ( & mut  self ,  lifetime_refs :  & [ hir:: Lifetime ] )  { 
1806+     fn  resolve_elided_lifetimes ( & mut  self ,  lifetime_refs :  & ' tcx   [ hir:: Lifetime ] )  { 
17621807        if  lifetime_refs. is_empty ( )  { 
17631808            return ; 
17641809        } 
@@ -1913,7 +1958,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19131958        } 
19141959    } 
19151960
1916-     fn  resolve_object_lifetime_default ( & mut  self ,  lifetime_ref :  & hir:: Lifetime )  { 
1961+     fn  resolve_object_lifetime_default ( & mut  self ,  lifetime_ref :  & ' tcx   hir:: Lifetime )  { 
19171962        let  mut  late_depth = 0 ; 
19181963        let  mut  scope = self . scope ; 
19191964        let  lifetime = loop  { 
@@ -1935,7 +1980,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19351980        self . insert_lifetime ( lifetime_ref,  lifetime. shifted ( late_depth) ) ; 
19361981    } 
19371982
1938-     fn  check_lifetime_defs ( & mut  self ,  old_scope :  ScopeRef ,  lifetimes :  & [ hir:: LifetimeDef ] )  { 
1983+     fn  check_lifetime_defs ( & mut  self ,  old_scope :  ScopeRef ,  lifetimes :  & ' tcx   [ hir:: LifetimeDef ] )  { 
19391984        for  i in  0 ..lifetimes. len ( )  { 
19401985            let  lifetime_i = & lifetimes[ i] ; 
19411986
@@ -2019,7 +2064,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20192064        } 
20202065    } 
20212066
2022-     fn  check_lifetime_def_for_shadowing ( & self ,  mut  old_scope :  ScopeRef ,  lifetime :  & hir:: Lifetime )  { 
2067+     fn  check_lifetime_def_for_shadowing ( & self , 
2068+                                         mut  old_scope :  ScopeRef , 
2069+                                         lifetime :  & ' tcx  hir:: Lifetime )  { 
20232070        for  & ( label,  label_span)  in  & self . labels_in_fn  { 
20242071            // FIXME (#24278): non-hygienic comparison 
20252072            if  lifetime. name . name ( )  == label { 
@@ -2068,7 +2115,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20682115        } 
20692116    } 
20702117
2071-     fn  insert_lifetime ( & mut  self ,  lifetime_ref :  & hir:: Lifetime ,  def :  Region )  { 
2118+     fn  insert_lifetime ( & mut  self ,  lifetime_ref :  & ' tcx   hir:: Lifetime ,  def :  Region )  { 
20722119        if  lifetime_ref. id  == ast:: DUMMY_NODE_ID  { 
20732120            span_bug ! ( 
20742121                lifetime_ref. span, 
@@ -2084,6 +2131,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20842131            self . tcx. sess. codemap( ) . span_to_string( lifetime_ref. span) 
20852132        ) ; 
20862133        self . map . defs . insert ( lifetime_ref. id ,  def) ; 
2134+ 
2135+         match  def { 
2136+             Region :: LateBoundAnon ( ..)  |
2137+             Region :: Static  => { 
2138+                 // These are anonymous lifetimes or lifetimes that are not declared. 
2139+             } 
2140+ 
2141+             Region :: Free ( _,  def_id)  |
2142+             Region :: LateBound ( _,  def_id,  _)  |
2143+             Region :: EarlyBound ( _,  def_id,  _)  => { 
2144+                 // A lifetime declared by the user. 
2145+                 if  !self . lifetime_uses . contains_key ( & def_id)  { 
2146+                     self . lifetime_uses 
2147+                         . insert ( def_id,  LifetimeUseSet :: One ( lifetime_ref) ) ; 
2148+                 }  else  { 
2149+                     self . lifetime_uses . insert ( def_id,  LifetimeUseSet :: Many ) ; 
2150+                 } 
2151+             } 
2152+         } 
20872153    } 
20882154} 
20892155
0 commit comments