@@ -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