@@ -142,28 +142,30 @@ impl WhenToSkip {
142142 }
143143}
144144
145- pub struct Interner < ' a > ( Option < & ' a Lifetime > ) ;
145+ pub enum Interner < ' a > {
146+ Middle ( & ' a Lifetime ) ,
147+ Generic ( Ident ) ,
148+ }
146149
147150impl < ' a > Interner < ' a > {
148- /// Return the `TyCtxt` interner for the given `structure`.
151+ /// Return the interner for the given `structure`.
149152 ///
150- /// If the input represented by `structure` has a `'tcx` lifetime parameter, then that will be used
151- /// used as the lifetime of the `TyCtxt`. Otherwise a `'tcx` lifetime parameter that is unrelated
152- /// to the input will be used.
153- fn resolve ( generics : & ' a Generics ) -> Self {
154- Self (
155- generics
156- . lifetimes ( )
157- . find_map ( |def| ( def. lifetime . ident == "tcx" ) . then_some ( & def. lifetime ) ) ,
158- )
153+ /// If the input represented by `structure` has a `'tcx` lifetime parameter, then `Middle('tcx)`
154+ /// will be returned; otherwise our derived implementation will be generic over a new parameter.
155+ fn resolve ( suffix : impl ToString , generics : & ' a Generics ) -> Self {
156+ generics
157+ . lifetimes ( )
158+ . find_map ( |def| ( def. lifetime . ident == "tcx" ) . then_some ( Self :: Middle ( & def. lifetime ) ) )
159+ . unwrap_or_else ( || Self :: Generic ( gen_param ( suffix, generics) ) )
159160 }
160161}
161162
162163impl ToTokens for Interner < ' _ > {
163164 fn to_tokens ( & self , tokens : & mut TokenStream ) {
164- let default = parse_quote ! { ' tcx } ;
165- let lt = self . 0 . unwrap_or ( & default) ;
166- tokens. extend ( quote ! { :: rustc_middle:: ty:: TyCtxt <#lt> } ) ;
165+ match self {
166+ Interner :: Middle ( lt) => tokens. extend ( quote ! { :: rustc_middle:: ty:: TyCtxt <#lt> } ) ,
167+ Interner :: Generic ( ident) => ident. to_tokens ( tokens) ,
168+ }
167169 }
168170}
169171
@@ -301,7 +303,7 @@ impl Interner<'_> {
301303
302304 if !referenced_ty_params. is_empty ( ) {
303305 Generic
304- } else if let Some ( interner) = & self . 0 && fields. into_iter ( ) . any ( |field| {
306+ } else if let Interner :: Middle ( interner) = self && fields. into_iter ( ) . any ( |field| {
305307 let mut info = Info { interner, contains_interner : false } ;
306308 info. visit_type ( & field. ty ) ;
307309 info. contains_interner
@@ -320,7 +322,7 @@ pub fn traversable_derive<T: Traversable>(
320322
321323 let ast = structure. ast ( ) ;
322324
323- let interner = Interner :: resolve ( & ast. generics ) ;
325+ let interner = Interner :: resolve ( "I" , & ast. generics ) ;
324326 let traverser = gen_param ( "T" , & ast. generics ) ;
325327 let traversable = T :: traversable ( & interner) ;
326328
@@ -331,8 +333,8 @@ pub fn traversable_derive<T: Traversable>(
331333 structure. add_bounds ( synstructure:: AddBounds :: None ) ;
332334 structure. bind_with ( |_| synstructure:: BindStyle :: Move ) ;
333335
334- let not_generic = if interner . 0 . is_none ( ) {
335- structure. add_impl_generic ( parse_quote ! { ' tcx } ) ;
336+ let not_generic = if let Interner :: Generic ( ident ) = & interner {
337+ structure. add_impl_generic ( parse_quote ! { #ident : :: rustc_type_ir :: Interner } ) ;
336338 Trivial
337339 } else {
338340 NotGeneric
0 commit comments