@@ -12,7 +12,7 @@ use rustc_trait_selection::traits::check_args_compatible;
1212use crate :: errors:: { DuplicateArg , NotParam } ;
1313use crate :: sig_types:: SpannedTypeVisitor ;
1414
15- struct OpaqueTypeCollector < ' tcx > {
15+ struct OpaqueTypeCollector < ' tcx , ' a > {
1616 tcx : TyCtxt < ' tcx > ,
1717 opaques : Vec < LocalDefId > ,
1818 /// The `DefId` of the item which we are collecting opaque types for.
@@ -21,31 +21,39 @@ struct OpaqueTypeCollector<'tcx> {
2121 /// Avoid infinite recursion due to recursive declarations.
2222 seen : FxHashSet < LocalDefId > ,
2323
24- span : Option < Span > ,
24+ get_span : & ' a dyn Fn ( & Self ) -> Span ,
2525
2626 mode : CollectionMode ,
2727}
2828
29+ #[ derive( Copy , Clone ) ]
2930enum CollectionMode {
3031 /// For impl trait in assoc types we only permit collecting them from
3132 /// associated types of the same impl block.
3233 ImplTraitInAssocTypes ,
3334 TypeAliasImplTraitTransition ,
3435}
3536
36- impl < ' tcx > OpaqueTypeCollector < ' tcx > {
37+ impl < ' tcx > OpaqueTypeCollector < ' tcx , ' _ > {
3738 fn new ( tcx : TyCtxt < ' tcx > , item : LocalDefId ) -> Self {
3839 let mode = match tcx. def_kind ( tcx. local_parent ( item) ) {
3940 DefKind :: Impl { of_trait : true } => CollectionMode :: ImplTraitInAssocTypes ,
4041 _ => CollectionMode :: TypeAliasImplTraitTransition ,
4142 } ;
42- Self { tcx, opaques : Vec :: new ( ) , item, seen : Default :: default ( ) , span : None , mode }
43+ Self {
44+ tcx,
45+ opaques : Vec :: new ( ) ,
46+ item,
47+ seen : Default :: default ( ) ,
48+ get_span : & |this| {
49+ this. tcx . def_ident_span ( this. item ) . unwrap_or_else ( || this. tcx . def_span ( this. item ) )
50+ } ,
51+ mode,
52+ }
4353 }
4454
4555 fn span ( & self ) -> Span {
46- self . span . unwrap_or_else ( || {
47- self . tcx . def_ident_span ( self . item ) . unwrap_or_else ( || self . tcx . def_span ( self . item ) )
48- } )
56+ ( self . get_span ) ( self )
4957 }
5058
5159 fn parent_trait_ref ( & self ) -> Option < ty:: TraitRef < ' tcx > > {
@@ -105,10 +113,10 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
105113 // Some things not necessarily have bodies, like method declarations in traits.
106114 let Some ( body_owner) = self . tcx . hir ( ) . maybe_body_owned_by ( self . item ) else { return } ;
107115 let body = self . tcx . hir ( ) . body ( body_owner) . value ;
108- struct TaitInBodyFinder < ' a , ' tcx > {
109- collector : & ' a mut OpaqueTypeCollector < ' tcx > ,
116+ struct TaitInBodyFinder < ' a , ' b , ' tcx > {
117+ collector : & ' a mut OpaqueTypeCollector < ' tcx , ' b > ,
110118 }
111- impl < ' v > intravisit:: Visitor < ' v > for TaitInBodyFinder < ' _ , ' _ > {
119+ impl < ' v > intravisit:: Visitor < ' v > for TaitInBodyFinder < ' _ , ' _ , ' _ > {
112120 #[ instrument( level = "trace" , skip( self ) ) ]
113121 fn visit_nested_item ( & mut self , id : rustc_hir:: ItemId ) {
114122 let id = id. owner_id . def_id ;
@@ -191,17 +199,25 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
191199 }
192200}
193201
194- impl < ' tcx > SpannedTypeVisitor < ' tcx > for OpaqueTypeCollector < ' tcx > {
202+ impl < ' tcx > SpannedTypeVisitor < ' tcx > for OpaqueTypeCollector < ' tcx , ' _ > {
195203 #[ instrument( skip( self ) , ret, level = "trace" ) ]
196204 fn visit ( & mut self , span : Span , value : impl TypeVisitable < TyCtxt < ' tcx > > ) {
197- let old = self . span ;
198- self . span = Some ( span) ;
199- value. visit_with ( self ) ;
200- self . span = old;
205+ let get_span = |_this : & _ | span;
206+ let mut nested = OpaqueTypeCollector {
207+ get_span : & get_span,
208+ tcx : self . tcx ,
209+ opaques : std:: mem:: take ( & mut self . opaques ) ,
210+ item : self . item ,
211+ seen : std:: mem:: take ( & mut self . seen ) ,
212+ mode : self . mode ,
213+ } ;
214+ value. visit_with ( & mut nested) ;
215+ self . opaques = nested. opaques ;
216+ self . seen = nested. seen ;
201217 }
202218}
203219
204- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OpaqueTypeCollector < ' tcx > {
220+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OpaqueTypeCollector < ' tcx , ' _ > {
205221 #[ instrument( skip( self ) , ret, level = "trace" ) ]
206222 fn visit_ty ( & mut self , t : Ty < ' tcx > ) {
207223 t. super_visit_with ( self ) ;
0 commit comments