@@ -25,20 +25,25 @@ pub enum Representability {
2525pub fn ty_is_representable < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > , sp : Span ) -> Representability {
2626 debug ! ( "is_type_representable: {:?}" , ty) ;
2727 // To avoid a stack overflow when checking an enum variant or struct that
28- // contains a different, structurally recursive type, maintain a stack
29- // of seen types and check recursion for each of them (issues #3008, #3779).
28+ // contains a different, structurally recursive type, maintain a stack of
29+ // seen types and check recursion for each of them (issues #3008, #3779,
30+ // #74224, #84611). `shadow_seen` contains the full stack and `seen` only
31+ // the one for the current type (e.g. if we have structs A and B, B contains
32+ // a field of type A, and we're currently looking at B, then `seen` will be
33+ // cleared when recursing to check A, but `shadow_seen` won't, so that we
34+ // can catch cases of mutual recursion where A also contains B).
3035 let mut seen: Vec < Ty < ' _ > > = Vec :: new ( ) ;
31- let mut shadow_seen: Vec < Ty < ' _ > > = Vec :: new ( ) ;
36+ let mut shadow_seen: Vec < & ' tcx ty :: AdtDef > = Vec :: new ( ) ;
3237 let mut representable_cache = FxHashMap :: default ( ) ;
33- let mut f_res = false ;
38+ let mut force_result = false ;
3439 let r = is_type_structurally_recursive (
3540 tcx,
3641 sp,
3742 & mut seen,
3843 & mut shadow_seen,
3944 & mut representable_cache,
4045 ty,
41- & mut f_res ,
46+ & mut force_result ,
4247 ) ;
4348 debug ! ( "is_type_representable: {:?} is {:?}" , ty, r) ;
4449 r
@@ -58,10 +63,10 @@ fn are_inner_types_recursive<'tcx>(
5863 tcx : TyCtxt < ' tcx > ,
5964 sp : Span ,
6065 seen : & mut Vec < Ty < ' tcx > > ,
61- shadow_seen : & mut Vec < Ty < ' tcx > > ,
66+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
6267 representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
6368 ty : Ty < ' tcx > ,
64- f_res : & mut bool ,
69+ force_result : & mut bool ,
6570) -> Representability {
6671 debug ! ( "are_inner_types_recursive({:?}, {:?}, {:?})" , ty, seen, shadow_seen) ;
6772 match ty. kind ( ) {
@@ -75,7 +80,7 @@ fn are_inner_types_recursive<'tcx>(
7580 shadow_seen,
7681 representable_cache,
7782 ty,
78- f_res ,
83+ force_result ,
7984 )
8085 } ) )
8186 }
@@ -88,7 +93,7 @@ fn are_inner_types_recursive<'tcx>(
8893 shadow_seen,
8994 representable_cache,
9095 ty,
91- f_res ,
96+ force_result ,
9297 ) ,
9398 ty:: Adt ( def, substs) => {
9499 // Find non representable fields with their spans
@@ -125,22 +130,12 @@ fn are_inner_types_recursive<'tcx>(
125130 // case (shadow_seen.first() is the type we are originally
126131 // interested in, and if we ever encounter the same AdtDef again,
127132 // we know that it must be SelfRecursive) and "forcibly" returning
128- // SelfRecursive (by setting f_res , which tells the calling
133+ // SelfRecursive (by setting force_result , which tells the calling
129134 // invocations of are_inner_types_representable to forward the
130135 // result without adjusting).
131- if shadow_seen. len ( ) > 1 && shadow_seen. len ( ) > seen. len ( ) {
132- match shadow_seen. first ( ) . map ( |ty| ty. kind ( ) ) {
133- Some ( ty:: Adt ( f_def, _) ) => {
134- if f_def == def {
135- * f_res = true ;
136- result = Some ( Representability :: SelfRecursive ( vec ! [ span] ) ) ;
137- }
138- }
139- Some ( _) => {
140- bug ! ( "shadow_seen stack contains non-ADT type: {:?}" , ty) ;
141- }
142- None => unreachable ! ( ) ,
143- }
136+ if shadow_seen. len ( ) > seen. len ( ) && shadow_seen. first ( ) == Some ( def) {
137+ * force_result = true ;
138+ result = Some ( Representability :: SelfRecursive ( vec ! [ span] ) ) ;
144139 }
145140
146141 if result == None {
@@ -154,15 +149,11 @@ fn are_inner_types_recursive<'tcx>(
154149 // If we have encountered an ADT definition that we have not seen
155150 // before (no need to check them twice), recurse to see whether that
156151 // definition is SelfRecursive. If so, we must be ContainsRecursive.
157- if shadow_seen. iter ( ) . len ( ) > 1
158- && !shadow_seen. iter ( ) . take ( shadow_seen. iter ( ) . len ( ) - 1 ) . any ( |seen_ty| {
159- match seen_ty. kind ( ) {
160- ty:: Adt ( seen_def, _) => seen_def == def,
161- _ => {
162- bug ! ( "seen stack contains non-ADT type: {:?}" , seen_ty) ;
163- }
164- }
165- } )
152+ if shadow_seen. len ( ) > 1
153+ && !shadow_seen
154+ . iter ( )
155+ . take ( shadow_seen. len ( ) - 1 )
156+ . any ( |seen_def| seen_def == def)
166157 {
167158 let adt_def_id = def. did ;
168159 let raw_adt_ty = tcx. type_of ( adt_def_id) ;
@@ -180,10 +171,10 @@ fn are_inner_types_recursive<'tcx>(
180171 shadow_seen,
181172 representable_cache,
182173 raw_adt_ty,
183- f_res ,
174+ force_result ,
184175 ) {
185176 Representability :: SelfRecursive ( _) => {
186- if * f_res {
177+ if * force_result {
187178 Representability :: SelfRecursive ( vec ! [ span] )
188179 } else {
189180 Representability :: ContainsRecursive
@@ -227,7 +218,7 @@ fn are_inner_types_recursive<'tcx>(
227218 shadow_seen,
228219 representable_cache,
229220 ty,
230- f_res ,
221+ force_result ,
231222 ) {
232223 Representability :: SelfRecursive ( _) => {
233224 Representability :: SelfRecursive ( vec ! [ span] )
@@ -263,10 +254,10 @@ fn is_type_structurally_recursive<'tcx>(
263254 tcx : TyCtxt < ' tcx > ,
264255 sp : Span ,
265256 seen : & mut Vec < Ty < ' tcx > > ,
266- shadow_seen : & mut Vec < Ty < ' tcx > > ,
257+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
267258 representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
268259 ty : Ty < ' tcx > ,
269- f_res : & mut bool ,
260+ force_result : & mut bool ,
270261) -> Representability {
271262 debug ! ( "is_type_structurally_recursive: {:?} {:?}" , ty, sp) ;
272263 if let Some ( representability) = representable_cache. get ( ty) {
@@ -284,7 +275,7 @@ fn is_type_structurally_recursive<'tcx>(
284275 shadow_seen,
285276 representable_cache,
286277 ty,
287- f_res ,
278+ force_result ,
288279 ) ;
289280
290281 representable_cache. insert ( ty, representability. clone ( ) ) ;
@@ -295,10 +286,10 @@ fn is_type_structurally_recursive_inner<'tcx>(
295286 tcx : TyCtxt < ' tcx > ,
296287 sp : Span ,
297288 seen : & mut Vec < Ty < ' tcx > > ,
298- shadow_seen : & mut Vec < Ty < ' tcx > > ,
289+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
299290 representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
300291 ty : Ty < ' tcx > ,
301- f_res : & mut bool ,
292+ force_result : & mut bool ,
302293) -> Representability {
303294 match ty. kind ( ) {
304295 ty:: Adt ( def, _) => {
@@ -346,23 +337,31 @@ fn is_type_structurally_recursive_inner<'tcx>(
346337 // For structs and enums, track all previously seen types by pushing them
347338 // onto the 'seen' stack.
348339 seen. push ( ty) ;
349- shadow_seen. push ( ty ) ;
340+ shadow_seen. push ( def ) ;
350341 let out = are_inner_types_recursive (
351342 tcx,
352343 sp,
353344 seen,
354345 shadow_seen,
355346 representable_cache,
356347 ty,
357- f_res ,
348+ force_result ,
358349 ) ;
359350 shadow_seen. pop ( ) ;
360351 seen. pop ( ) ;
361352 out
362353 }
363354 _ => {
364355 // No need to push in other cases.
365- are_inner_types_recursive ( tcx, sp, seen, shadow_seen, representable_cache, ty, f_res)
356+ are_inner_types_recursive (
357+ tcx,
358+ sp,
359+ seen,
360+ shadow_seen,
361+ representable_cache,
362+ ty,
363+ force_result,
364+ )
366365 }
367366 }
368367}
0 commit comments