diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index ae2ab32ef53..56fb12d3c22 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>( StubInfo { metadata, unique_type_id } } +struct AdtStackPopGuard<'ll, 'tcx, 'a> { + cx: &'a CodegenCx<'ll, 'tcx>, +} + +impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> { + fn drop(&mut self) { + debug_context(self.cx).adt_stack.borrow_mut().pop(); + } +} + /// This function enables creating debuginfo nodes that can recursively refer to themselves. /// It will first insert the given stub into the type map and only then execute the `members` /// 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>( ) -> DINodeCreationResult<'ll> { assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None); + let mut _adt_stack_pop_guard = None; + if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id + && let ty::Adt(adt_def, args) = ty.kind() + { + let def_id = adt_def.did(); + // If any sub type reference the original type definition and the sub type has a type + // parameter that strictly contains the original parameter, the original type is a recursive + // type that can expanding indefinitely. Example, + // ``` + // enum Recursive { + // Recurse(*const Recursive>), + // Item(T), + // } + // ``` + let is_expanding_recursive = + debug_context(cx).adt_stack.borrow().iter().any(|(parent_def_id, parent_args)| { + if def_id == *parent_def_id { + args.iter().zip(parent_args.iter()).any(|(arg, parent_arg)| { + if let (Some(arg), Some(parent_arg)) = (arg.as_type(), parent_arg.as_type()) + { + arg != parent_arg && arg.contains(parent_arg) + } else { + false + } + }) + } else { + false + } + }); + if is_expanding_recursive { + // FIXME: indicate that this is an expanding recursive type in stub metadata? + return DINodeCreationResult::new(stub_info.metadata, false); + } else { + debug_context(cx).adt_stack.borrow_mut().push((def_id, args)); + _adt_stack_pop_guard = Some(AdtStackPopGuard { cx }); + } + } + debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata); let members: SmallVec<_> = diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 0f94a1dbb0d..c5085927923 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -66,6 +66,7 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { created_files: RefCell, &'ll DIFile>>, type_map: metadata::TypeMap<'ll, 'tcx>, + adt_stack: RefCell)>>, namespace_map: RefCell>, recursion_marker_type: OnceCell<&'ll DIType>, } @@ -80,6 +81,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { builder, created_files: Default::default(), type_map: Default::default(), + adt_stack: Default::default(), namespace_map: RefCell::new(Default::default()), recursion_marker_type: OnceCell::new(), } diff --git a/tests/crashes/100618.rs b/tests/crashes/100618.rs deleted file mode 100644 index 911c4098bad..00000000000 --- a/tests/crashes/100618.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #100618 -//@ compile-flags: -Cdebuginfo=2 - -//@ only-x86_64 -enum Foo { - Value(T), - Recursive(&'static Foo>), -} - -fn main() { - let _x = Foo::Value(()); -} diff --git a/tests/crashes/115994.rs b/tests/crashes/115994.rs deleted file mode 100644 index 23d1507136f..00000000000 --- a/tests/crashes/115994.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #115994 -//@ compile-flags: -Cdebuginfo=2 --crate-type lib - -// To prevent "overflow while adding drop-check rules". -use std::mem::ManuallyDrop; - -pub enum Foo { - Leaf(U), - - Branch(BoxedFoo>), -} - -pub type BoxedFoo = ManuallyDrop>>; - -pub fn test() -> Foo { - todo!() -} diff --git a/tests/crashes/121538.rs b/tests/crashes/121538.rs deleted file mode 100644 index f18bad84b57..00000000000 --- a/tests/crashes/121538.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: #121538 -//@ compile-flags: -Cdebuginfo=2 - -use std::marker::PhantomData; - -struct Digit { - elem: T -} - -struct Node { m: PhantomData<&'static T> } - -enum FingerTree { - Single(T), - - Deep( - Digit, - Node>>, - ) -} - -enum Wrapper { - Simple, - Other(FingerTree), -} - -fn main() { - let w = - Some(Wrapper::Simple::); - -} diff --git a/tests/debuginfo/recursive-enum.rs b/tests/debuginfo/recursive-enum.rs index c2c3e71b8a4..b861e6d617c 100644 --- a/tests/debuginfo/recursive-enum.rs +++ b/tests/debuginfo/recursive-enum.rs @@ -4,7 +4,7 @@ // gdb-command:run // Test whether compiling a recursive enum definition crashes debug info generation. The test case -// is taken from issue #11083. +// is taken from issue #11083 and #135093. #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -18,6 +18,21 @@ struct WindowCallbacks<'a> { pos_callback: Option>, } +enum ExpandingRecursive { + Recurse(Indirect), + Item(T), +} + +struct Indirect { + rec: *const ExpandingRecursive>, +} + + fn main() { let x = WindowCallbacks { pos_callback: None }; + + // EXPANDING RECURSIVE + let expanding_recursive: ExpandingRecursive = ExpandingRecursive::Recurse(Indirect { + rec: &ExpandingRecursive::Item(Option::Some(42)), + }); } diff --git a/tests/crashes/107362.rs b/tests/debuginfo/recursive-type-with-gat.rs similarity index 96% rename from tests/crashes/107362.rs rename to tests/debuginfo/recursive-type-with-gat.rs index 8d55d611eb1..b8a67d8d24b 100644 --- a/tests/crashes/107362.rs +++ b/tests/debuginfo/recursive-type-with-gat.rs @@ -1,4 +1,3 @@ -//@ known-bug: #107362 //@ compile-flags: -Cdebuginfo=2 pub trait Functor