@@ -25,20 +25,25 @@ pub enum Representability {
25
25
pub fn ty_is_representable < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > , sp : Span ) -> Representability {
26
26
debug ! ( "is_type_representable: {:?}" , ty) ;
27
27
// 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).
30
35
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 ( ) ;
32
37
let mut representable_cache = FxHashMap :: default ( ) ;
33
- let mut f_res = false ;
38
+ let mut force_result = false ;
34
39
let r = is_type_structurally_recursive (
35
40
tcx,
36
41
sp,
37
42
& mut seen,
38
43
& mut shadow_seen,
39
44
& mut representable_cache,
40
45
ty,
41
- & mut f_res ,
46
+ & mut force_result ,
42
47
) ;
43
48
debug ! ( "is_type_representable: {:?} is {:?}" , ty, r) ;
44
49
r
@@ -58,10 +63,10 @@ fn are_inner_types_recursive<'tcx>(
58
63
tcx : TyCtxt < ' tcx > ,
59
64
sp : Span ,
60
65
seen : & mut Vec < Ty < ' tcx > > ,
61
- shadow_seen : & mut Vec < Ty < ' tcx > > ,
66
+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
62
67
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
63
68
ty : Ty < ' tcx > ,
64
- f_res : & mut bool ,
69
+ force_result : & mut bool ,
65
70
) -> Representability {
66
71
debug ! ( "are_inner_types_recursive({:?}, {:?}, {:?})" , ty, seen, shadow_seen) ;
67
72
match ty. kind ( ) {
@@ -75,7 +80,7 @@ fn are_inner_types_recursive<'tcx>(
75
80
shadow_seen,
76
81
representable_cache,
77
82
ty,
78
- f_res ,
83
+ force_result ,
79
84
)
80
85
} ) )
81
86
}
@@ -88,7 +93,7 @@ fn are_inner_types_recursive<'tcx>(
88
93
shadow_seen,
89
94
representable_cache,
90
95
ty,
91
- f_res ,
96
+ force_result ,
92
97
) ,
93
98
ty:: Adt ( def, substs) => {
94
99
// Find non representable fields with their spans
@@ -125,22 +130,12 @@ fn are_inner_types_recursive<'tcx>(
125
130
// case (shadow_seen.first() is the type we are originally
126
131
// interested in, and if we ever encounter the same AdtDef again,
127
132
// 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
129
134
// invocations of are_inner_types_representable to forward the
130
135
// 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] ) ) ;
144
139
}
145
140
146
141
if result == None {
@@ -154,15 +149,11 @@ fn are_inner_types_recursive<'tcx>(
154
149
// If we have encountered an ADT definition that we have not seen
155
150
// before (no need to check them twice), recurse to see whether that
156
151
// 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)
166
157
{
167
158
let adt_def_id = def. did ;
168
159
let raw_adt_ty = tcx. type_of ( adt_def_id) ;
@@ -180,10 +171,10 @@ fn are_inner_types_recursive<'tcx>(
180
171
shadow_seen,
181
172
representable_cache,
182
173
raw_adt_ty,
183
- f_res ,
174
+ force_result ,
184
175
) {
185
176
Representability :: SelfRecursive ( _) => {
186
- if * f_res {
177
+ if * force_result {
187
178
Representability :: SelfRecursive ( vec ! [ span] )
188
179
} else {
189
180
Representability :: ContainsRecursive
@@ -227,7 +218,7 @@ fn are_inner_types_recursive<'tcx>(
227
218
shadow_seen,
228
219
representable_cache,
229
220
ty,
230
- f_res ,
221
+ force_result ,
231
222
) {
232
223
Representability :: SelfRecursive ( _) => {
233
224
Representability :: SelfRecursive ( vec ! [ span] )
@@ -263,10 +254,10 @@ fn is_type_structurally_recursive<'tcx>(
263
254
tcx : TyCtxt < ' tcx > ,
264
255
sp : Span ,
265
256
seen : & mut Vec < Ty < ' tcx > > ,
266
- shadow_seen : & mut Vec < Ty < ' tcx > > ,
257
+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
267
258
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
268
259
ty : Ty < ' tcx > ,
269
- f_res : & mut bool ,
260
+ force_result : & mut bool ,
270
261
) -> Representability {
271
262
debug ! ( "is_type_structurally_recursive: {:?} {:?}" , ty, sp) ;
272
263
if let Some ( representability) = representable_cache. get ( ty) {
@@ -284,7 +275,7 @@ fn is_type_structurally_recursive<'tcx>(
284
275
shadow_seen,
285
276
representable_cache,
286
277
ty,
287
- f_res ,
278
+ force_result ,
288
279
) ;
289
280
290
281
representable_cache. insert ( ty, representability. clone ( ) ) ;
@@ -295,10 +286,10 @@ fn is_type_structurally_recursive_inner<'tcx>(
295
286
tcx : TyCtxt < ' tcx > ,
296
287
sp : Span ,
297
288
seen : & mut Vec < Ty < ' tcx > > ,
298
- shadow_seen : & mut Vec < Ty < ' tcx > > ,
289
+ shadow_seen : & mut Vec < & ' tcx ty :: AdtDef > ,
299
290
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
300
291
ty : Ty < ' tcx > ,
301
- f_res : & mut bool ,
292
+ force_result : & mut bool ,
302
293
) -> Representability {
303
294
match ty. kind ( ) {
304
295
ty:: Adt ( def, _) => {
@@ -346,23 +337,31 @@ fn is_type_structurally_recursive_inner<'tcx>(
346
337
// For structs and enums, track all previously seen types by pushing them
347
338
// onto the 'seen' stack.
348
339
seen. push ( ty) ;
349
- shadow_seen. push ( ty ) ;
340
+ shadow_seen. push ( def ) ;
350
341
let out = are_inner_types_recursive (
351
342
tcx,
352
343
sp,
353
344
seen,
354
345
shadow_seen,
355
346
representable_cache,
356
347
ty,
357
- f_res ,
348
+ force_result ,
358
349
) ;
359
350
shadow_seen. pop ( ) ;
360
351
seen. pop ( ) ;
361
352
out
362
353
}
363
354
_ => {
364
355
// 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
+ )
366
365
}
367
366
}
368
367
}
0 commit comments