@@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>(
247
247
StubInfo { metadata, unique_type_id }
248
248
}
249
249
250
+ struct AdtStackPopGuard < ' ll , ' tcx , ' a > {
251
+ cx : & ' a CodegenCx < ' ll , ' tcx > ,
252
+ }
253
+
254
+ impl < ' ll , ' tcx , ' a > Drop for AdtStackPopGuard < ' ll , ' tcx , ' a > {
255
+ fn drop ( & mut self ) {
256
+ debug_context ( self . cx ) . adt_stack . borrow_mut ( ) . pop ( ) ;
257
+ }
258
+ }
259
+
250
260
/// This function enables creating debuginfo nodes that can recursively refer to themselves.
251
261
/// It will first insert the given stub into the type map and only then execute the `members`
252
262
/// and `generics` closures passed in. These closures have access to the stub so they can
@@ -261,6 +271,44 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
261
271
) -> DINodeCreationResult < ' ll > {
262
272
assert_eq ! ( debug_context( cx) . type_map. di_node_for_unique_id( stub_info. unique_type_id) , None ) ;
263
273
274
+ let mut _adt_stack_pop_guard = None ;
275
+ if let UniqueTypeId :: Ty ( ty, ..) = stub_info. unique_type_id
276
+ && let ty:: Adt ( adt_def, args) = ty. kind ( )
277
+ {
278
+ let def_id = adt_def. did ( ) ;
279
+ // If any sub type reference the original type definition and the sub type has a type
280
+ // parameter that strictly contains the original parameter, the original type is a recursive
281
+ // type that can expanding indefinitely. Example,
282
+ // ```
283
+ // enum Recursive<T> {
284
+ // Recurse(*const Recursive<Wrap<T>>),
285
+ // Item(T),
286
+ // }
287
+ // ```
288
+ let is_expanding_recursive =
289
+ debug_context ( cx) . adt_stack . borrow ( ) . iter ( ) . any ( |( parent_def_id, parent_args) | {
290
+ if def_id == * parent_def_id {
291
+ args. iter ( ) . zip ( parent_args. iter ( ) ) . any ( |( arg, parent_arg) | {
292
+ if let ( Some ( arg) , Some ( parent_arg) ) = ( arg. as_type ( ) , parent_arg. as_type ( ) )
293
+ {
294
+ arg != parent_arg && arg. contains ( parent_arg)
295
+ } else {
296
+ false
297
+ }
298
+ } )
299
+ } else {
300
+ false
301
+ }
302
+ } ) ;
303
+ if is_expanding_recursive {
304
+ // FIXME: indicate that this is an expanding recursive type in stub metadata?
305
+ return DINodeCreationResult :: new ( stub_info. metadata , false ) ;
306
+ } else {
307
+ debug_context ( cx) . adt_stack . borrow_mut ( ) . push ( ( def_id, args) ) ;
308
+ _adt_stack_pop_guard = Some ( AdtStackPopGuard { cx } ) ;
309
+ }
310
+ }
311
+
264
312
debug_context ( cx) . type_map . insert ( stub_info. unique_type_id , stub_info. metadata ) ;
265
313
266
314
let members: SmallVec < _ > =
0 commit comments