@@ -17,12 +17,20 @@ use std::cmp;
17
17
pub enum Representability {
18
18
Representable ,
19
19
ContainsRecursive ,
20
- SelfRecursive ( Vec < Span > ) ,
20
+ /// Return a list of types that are included in themselves:
21
+ /// the spans where they are self-included, and (if found)
22
+ /// the HirId of the FieldDef that defines the self-inclusion.
23
+ SelfRecursive ( Vec < ( Span , Option < hir:: HirId > ) > ) ,
21
24
}
22
25
23
26
/// Check whether a type is representable. This means it cannot contain unboxed
24
27
/// structural recursion. This check is needed for structs and enums.
25
- pub fn ty_is_representable < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > , sp : Span ) -> Representability {
28
+ pub fn ty_is_representable < ' tcx > (
29
+ tcx : TyCtxt < ' tcx > ,
30
+ ty : Ty < ' tcx > ,
31
+ sp : Span ,
32
+ field_id : Option < hir:: HirId > ,
33
+ ) -> Representability {
26
34
debug ! ( "is_type_representable: {:?}" , ty) ;
27
35
// To avoid a stack overflow when checking an enum variant or struct that
28
36
// contains a different, structurally recursive type, maintain a stack of
@@ -38,11 +46,12 @@ pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> R
38
46
let mut force_result = false ;
39
47
let r = is_type_structurally_recursive (
40
48
tcx,
41
- sp,
42
49
& mut seen,
43
50
& mut shadow_seen,
44
51
& mut representable_cache,
45
52
ty,
53
+ sp,
54
+ field_id,
46
55
& mut force_result,
47
56
) ;
48
57
debug ! ( "is_type_representable: {:?} is {:?}" , ty, r) ;
@@ -61,11 +70,12 @@ fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representabilit
61
70
62
71
fn are_inner_types_recursive < ' tcx > (
63
72
tcx : TyCtxt < ' tcx > ,
64
- sp : Span ,
65
73
seen : & mut Vec < Ty < ' tcx > > ,
66
74
shadow_seen : & mut Vec < ty:: AdtDef < ' tcx > > ,
67
75
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
68
76
ty : Ty < ' tcx > ,
77
+ sp : Span ,
78
+ field_id : Option < hir:: HirId > ,
69
79
force_result : & mut bool ,
70
80
) -> Representability {
71
81
debug ! ( "are_inner_types_recursive({:?}, {:?}, {:?})" , ty, seen, shadow_seen) ;
@@ -75,11 +85,12 @@ fn are_inner_types_recursive<'tcx>(
75
85
fold_repr ( fields. iter ( ) . map ( |ty| {
76
86
is_type_structurally_recursive (
77
87
tcx,
78
- sp,
79
88
seen,
80
89
shadow_seen,
81
90
representable_cache,
82
91
ty,
92
+ sp,
93
+ field_id,
83
94
force_result,
84
95
)
85
96
} ) )
@@ -88,20 +99,26 @@ fn are_inner_types_recursive<'tcx>(
88
99
// FIXME(#11924) Behavior undecided for zero-length vectors.
89
100
ty:: Array ( ty, _) => is_type_structurally_recursive (
90
101
tcx,
91
- sp,
92
102
seen,
93
103
shadow_seen,
94
104
representable_cache,
95
105
* ty,
106
+ sp,
107
+ field_id,
96
108
force_result,
97
109
) ,
98
110
ty:: Adt ( def, substs) => {
99
111
// Find non representable fields with their spans
100
112
fold_repr ( def. all_fields ( ) . map ( |field| {
101
113
let ty = field. ty ( tcx, substs) ;
102
- let span = match field. did . as_local ( ) . and_then ( |id| tcx. hir ( ) . find_by_def_id ( id) ) {
103
- Some ( hir:: Node :: Field ( field) ) => field. ty . span ,
104
- _ => sp,
114
+ let ( sp, field_id) = match field
115
+ . did
116
+ . as_local ( )
117
+ . map ( |id| tcx. hir ( ) . local_def_id_to_hir_id ( id) )
118
+ . and_then ( |id| tcx. hir ( ) . find ( id) )
119
+ {
120
+ Some ( hir:: Node :: Field ( field) ) => ( field. ty . span , Some ( field. hir_id ) ) ,
121
+ _ => ( sp, field_id) ,
105
122
} ;
106
123
107
124
let mut result = None ;
@@ -130,7 +147,7 @@ fn are_inner_types_recursive<'tcx>(
130
147
// result without adjusting).
131
148
if shadow_seen. len ( ) > seen. len ( ) && shadow_seen. first ( ) == Some ( def) {
132
149
* force_result = true ;
133
- result = Some ( Representability :: SelfRecursive ( vec ! [ span ] ) ) ;
150
+ result = Some ( Representability :: SelfRecursive ( vec ! [ ( sp , field_id ) ] ) ) ;
134
151
}
135
152
136
153
if result == None {
@@ -161,16 +178,17 @@ fn are_inner_types_recursive<'tcx>(
161
178
result = Some (
162
179
match is_type_structurally_recursive (
163
180
tcx,
164
- span,
165
181
& mut nested_seen,
166
182
shadow_seen,
167
183
representable_cache,
168
184
raw_adt_ty,
185
+ sp,
186
+ field_id,
169
187
force_result,
170
188
) {
171
189
Representability :: SelfRecursive ( _) => {
172
190
if * force_result {
173
- Representability :: SelfRecursive ( vec ! [ span ] )
191
+ Representability :: SelfRecursive ( vec ! [ ( sp , field_id ) ] )
174
192
} else {
175
193
Representability :: ContainsRecursive
176
194
}
@@ -208,15 +226,16 @@ fn are_inner_types_recursive<'tcx>(
208
226
result = Some (
209
227
match is_type_structurally_recursive (
210
228
tcx,
211
- span,
212
229
seen,
213
230
shadow_seen,
214
231
representable_cache,
215
232
ty,
233
+ sp,
234
+ field_id,
216
235
force_result,
217
236
) {
218
237
Representability :: SelfRecursive ( _) => {
219
- Representability :: SelfRecursive ( vec ! [ span ] )
238
+ Representability :: SelfRecursive ( vec ! [ ( sp , field_id ) ] )
220
239
}
221
240
x => x,
222
241
} ,
@@ -247,29 +266,31 @@ fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
247
266
// contain any types on stack `seen`?
248
267
fn is_type_structurally_recursive < ' tcx > (
249
268
tcx : TyCtxt < ' tcx > ,
250
- sp : Span ,
251
269
seen : & mut Vec < Ty < ' tcx > > ,
252
270
shadow_seen : & mut Vec < ty:: AdtDef < ' tcx > > ,
253
271
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
254
272
ty : Ty < ' tcx > ,
273
+ sp : Span ,
274
+ field_id : Option < hir:: HirId > ,
255
275
force_result : & mut bool ,
256
276
) -> Representability {
257
- debug ! ( "is_type_structurally_recursive: {:?} {:?}" , ty, sp) ;
277
+ debug ! ( "is_type_structurally_recursive: {:?} {:?} {:?} " , ty, sp, field_id ) ;
258
278
if let Some ( representability) = representable_cache. get ( & ty) {
259
279
debug ! (
260
- "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}" ,
261
- ty, sp, representability
280
+ "is_type_structurally_recursive: {:?} {:?} {:?} - (cached) {:?}" ,
281
+ ty, sp, field_id , representability
262
282
) ;
263
283
return representability. clone ( ) ;
264
284
}
265
285
266
286
let representability = is_type_structurally_recursive_inner (
267
287
tcx,
268
- sp,
269
288
seen,
270
289
shadow_seen,
271
290
representable_cache,
272
291
ty,
292
+ sp,
293
+ field_id,
273
294
force_result,
274
295
) ;
275
296
@@ -279,11 +300,12 @@ fn is_type_structurally_recursive<'tcx>(
279
300
280
301
fn is_type_structurally_recursive_inner < ' tcx > (
281
302
tcx : TyCtxt < ' tcx > ,
282
- sp : Span ,
283
303
seen : & mut Vec < Ty < ' tcx > > ,
284
304
shadow_seen : & mut Vec < ty:: AdtDef < ' tcx > > ,
285
305
representable_cache : & mut FxHashMap < Ty < ' tcx > , Representability > ,
286
306
ty : Ty < ' tcx > ,
307
+ sp : Span ,
308
+ field_id : Option < hir:: HirId > ,
287
309
force_result : & mut bool ,
288
310
) -> Representability {
289
311
match ty. kind ( ) {
@@ -305,7 +327,7 @@ fn is_type_structurally_recursive_inner<'tcx>(
305
327
if let Some ( & seen_adt) = iter. next ( ) {
306
328
if same_adt ( seen_adt, * def) {
307
329
debug ! ( "SelfRecursive: {:?} contains {:?}" , seen_adt, ty) ;
308
- return Representability :: SelfRecursive ( vec ! [ sp ] ) ;
330
+ return Representability :: SelfRecursive ( vec ! [ ( sp , field_id ) ] ) ;
309
331
}
310
332
}
311
333
@@ -335,11 +357,12 @@ fn is_type_structurally_recursive_inner<'tcx>(
335
357
shadow_seen. push ( * def) ;
336
358
let out = are_inner_types_recursive (
337
359
tcx,
338
- sp,
339
360
seen,
340
361
shadow_seen,
341
362
representable_cache,
342
363
ty,
364
+ sp,
365
+ field_id,
343
366
force_result,
344
367
) ;
345
368
shadow_seen. pop ( ) ;
@@ -350,11 +373,12 @@ fn is_type_structurally_recursive_inner<'tcx>(
350
373
// No need to push in other cases.
351
374
are_inner_types_recursive (
352
375
tcx,
353
- sp,
354
376
seen,
355
377
shadow_seen,
356
378
representable_cache,
357
379
ty,
380
+ sp,
381
+ field_id,
358
382
force_result,
359
383
)
360
384
}
0 commit comments