@@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>(
247247 StubInfo { metadata, unique_type_id }
248248}
249249
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+
250260/// This function enables creating debuginfo nodes that can recursively refer to themselves.
251261/// It will first insert the given stub into the type map and only then execute the `members`
252262/// 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>(
261271) -> DINodeCreationResult < ' ll > {
262272 assert_eq ! ( debug_context( cx) . type_map. di_node_for_unique_id( stub_info. unique_type_id) , None ) ;
263273
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+
264312 debug_context ( cx) . type_map . insert ( stub_info. unique_type_id , stub_info. metadata ) ;
265313
266314 let members: SmallVec < _ > =
0 commit comments