1use std::cell::RefCell;
2
3use libc::c_uint;
4use rustc_abi::{Align, Size, VariantIdx};
5use rustc_data_structures::fingerprint::Fingerprint;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_data_structures::stable_hasher::{StableHash, StableHasher};
8use rustc_macros::StableHash;
9use rustc_middle::bug;
10use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt, Unnormalized};
11
12use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
13use crate::common::CodegenCx;
14use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
15use crate::llvm;
16use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
17
18mod private {
19 use rustc_macros::StableHash;
20
21 #[derive(#[automatically_derived]
impl ::core::fmt::Debug for HiddenZst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "HiddenZst")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for HiddenZst {
#[inline]
fn clone(&self) -> HiddenZst { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for HiddenZst { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for HiddenZst {
#[inline]
fn eq(&self, other: &HiddenZst) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for HiddenZst {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for HiddenZst {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, const _: () =
{
impl ::rustc_data_structures::stable_hasher::StableHash for HiddenZst
{
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self { HiddenZst => {} }
}
}
};StableHash)]
26 pub(crate) struct HiddenZst;
27}
28
29#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for UniqueTypeId<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
UniqueTypeId::Ty(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Ty",
__self_0, &__self_1),
UniqueTypeId::VariantPart(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"VariantPart", __self_0, &__self_1),
UniqueTypeId::VariantStructType(__self_0, __self_1, __self_2) =>
::core::fmt::Formatter::debug_tuple_field3_finish(f,
"VariantStructType", __self_0, __self_1, &__self_2),
UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0, __self_1,
__self_2) =>
::core::fmt::Formatter::debug_tuple_field3_finish(f,
"VariantStructTypeCppLikeWrapper", __self_0, __self_1,
&__self_2),
UniqueTypeId::VTableTy(__self_0, __self_1, __self_2) =>
::core::fmt::Formatter::debug_tuple_field3_finish(f,
"VTableTy", __self_0, __self_1, &__self_2),
}
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for UniqueTypeId<'tcx> {
#[inline]
fn clone(&self) -> UniqueTypeId<'tcx> {
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<VariantIdx>;
let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _:
::core::clone::AssertParamIsClone<Option<ExistentialTraitRef<'tcx>>>;
let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for UniqueTypeId<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for UniqueTypeId<'tcx> {
#[inline]
fn eq(&self, other: &UniqueTypeId<'tcx>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(UniqueTypeId::Ty(__self_0, __self_1),
UniqueTypeId::Ty(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(UniqueTypeId::VariantPart(__self_0, __self_1),
UniqueTypeId::VariantPart(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(UniqueTypeId::VariantStructType(__self_0, __self_1,
__self_2),
UniqueTypeId::VariantStructType(__arg1_0, __arg1_1,
__arg1_2)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0,
__self_1, __self_2),
UniqueTypeId::VariantStructTypeCppLikeWrapper(__arg1_0,
__arg1_1, __arg1_2)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(UniqueTypeId::VTableTy(__self_0, __self_1, __self_2),
UniqueTypeId::VTableTy(__arg1_0, __arg1_1, __arg1_2)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for UniqueTypeId<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _:
::core::cmp::AssertParamIsEq<Option<ExistentialTraitRef<'tcx>>>;
let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for UniqueTypeId<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
UniqueTypeId::Ty(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
UniqueTypeId::VariantPart(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
UniqueTypeId::VariantStructType(__self_0, __self_1, __self_2) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state);
::core::hash::Hash::hash(__self_2, state)
}
UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0, __self_1,
__self_2) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state);
::core::hash::Hash::hash(__self_2, state)
}
UniqueTypeId::VTableTy(__self_0, __self_1, __self_2) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state);
::core::hash::Hash::hash(__self_2, state)
}
}
}
}Hash, const _: () =
{
impl<'tcx> ::rustc_data_structures::stable_hasher::StableHash for
UniqueTypeId<'tcx> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
UniqueTypeId::Ty(ref __binding_0, ref __binding_1) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
UniqueTypeId::VariantPart(ref __binding_0, ref __binding_1)
=> {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
UniqueTypeId::VariantStructType(ref __binding_0,
ref __binding_1, ref __binding_2) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
{ __binding_2.stable_hash(__hcx, __hasher); }
}
UniqueTypeId::VariantStructTypeCppLikeWrapper(ref __binding_0,
ref __binding_1, ref __binding_2) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
{ __binding_2.stable_hash(__hcx, __hasher); }
}
UniqueTypeId::VTableTy(ref __binding_0, ref __binding_1,
ref __binding_2) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
{ __binding_2.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
37pub(super) enum UniqueTypeId<'tcx> {
38 Ty(Ty<'tcx>, private::HiddenZst),
40 VariantPart(Ty<'tcx>, private::HiddenZst),
43 VariantStructType(Ty<'tcx>, VariantIdx, private::HiddenZst),
45 VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst),
47 VTableTy(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>, private::HiddenZst),
49}
50
51impl<'tcx> UniqueTypeId<'tcx> {
52 pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
53 match (&t,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(t))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
54 t,
55 tcx.normalize_erasing_regions(
56 ty::TypingEnv::fully_monomorphized(),
57 Unnormalized::new_wip(t)
58 )
59 );
60 UniqueTypeId::Ty(t, private::HiddenZst)
61 }
62
63 pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
64 match (&enum_ty,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(enum_ty))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
65 enum_ty,
66 tcx.normalize_erasing_regions(
67 ty::TypingEnv::fully_monomorphized(),
68 Unnormalized::new_wip(enum_ty)
69 )
70 );
71 UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
72 }
73
74 pub(crate) fn for_enum_variant_struct_type(
75 tcx: TyCtxt<'tcx>,
76 enum_ty: Ty<'tcx>,
77 variant_idx: VariantIdx,
78 ) -> Self {
79 match (&enum_ty,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(enum_ty))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
80 enum_ty,
81 tcx.normalize_erasing_regions(
82 ty::TypingEnv::fully_monomorphized(),
83 Unnormalized::new_wip(enum_ty)
84 )
85 );
86 UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
87 }
88
89 pub(crate) fn for_enum_variant_struct_type_wrapper(
90 tcx: TyCtxt<'tcx>,
91 enum_ty: Ty<'tcx>,
92 variant_idx: VariantIdx,
93 ) -> Self {
94 match (&enum_ty,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(enum_ty))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
95 enum_ty,
96 tcx.normalize_erasing_regions(
97 ty::TypingEnv::fully_monomorphized(),
98 Unnormalized::new_wip(enum_ty)
99 )
100 );
101 UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
102 }
103
104 pub(crate) fn for_vtable_ty(
105 tcx: TyCtxt<'tcx>,
106 self_type: Ty<'tcx>,
107 implemented_trait: Option<ExistentialTraitRef<'tcx>>,
108 ) -> Self {
109 match (&self_type,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(self_type))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
110 self_type,
111 tcx.normalize_erasing_regions(
112 ty::TypingEnv::fully_monomorphized(),
113 Unnormalized::new_wip(self_type)
114 )
115 );
116 match (&implemented_trait,
&tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
Unnormalized::new_wip(implemented_trait))) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(
117 implemented_trait,
118 tcx.normalize_erasing_regions(
119 ty::TypingEnv::fully_monomorphized(),
120 Unnormalized::new_wip(implemented_trait)
121 )
122 );
123 UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst)
124 }
125
126 fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String {
131 let mut hasher = StableHasher::new();
132 tcx.with_stable_hashing_context(|mut hcx| {
133 hcx.while_hashing_spans(false, |hcx| self.stable_hash(hcx, &mut hasher))
134 });
135 hasher.finish::<Fingerprint>().to_hex()
136 }
137
138 pub(crate) fn expect_ty(self) -> Ty<'tcx> {
139 match self {
140 UniqueTypeId::Ty(ty, _) => ty,
141 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("Expected `UniqueTypeId::Ty` but found `{0:?}`",
self))bug!("Expected `UniqueTypeId::Ty` but found `{:?}`", self),
142 }
143 }
144}
145
146#[derive(#[automatically_derived]
impl<'ll, 'tcx> ::core::default::Default for TypeMap<'ll, 'tcx> {
#[inline]
fn default() -> TypeMap<'ll, 'tcx> {
TypeMap { unique_id_to_di_node: ::core::default::Default::default() }
}
}Default)]
149pub(crate) struct TypeMap<'ll, 'tcx> {
150 pub(super) unique_id_to_di_node: RefCell<FxHashMap<UniqueTypeId<'tcx>, &'ll DIType>>,
151}
152
153impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
154 pub(super) fn insert(&self, unique_type_id: UniqueTypeId<'tcx>, metadata: &'ll DIType) {
157 if self.unique_id_to_di_node.borrow_mut().insert(unique_type_id, metadata).is_some() {
158 ::rustc_middle::util::bug::bug_fmt(format_args!("type metadata for unique ID \'{0:?}\' is already in the `TypeMap`!",
unique_type_id));bug!("type metadata for unique ID '{:?}' is already in the `TypeMap`!", unique_type_id);
159 }
160 }
161
162 pub(super) fn di_node_for_unique_id(
163 &self,
164 unique_type_id: UniqueTypeId<'tcx>,
165 ) -> Option<&'ll DIType> {
166 self.unique_id_to_di_node.borrow().get(&unique_type_id).cloned()
167 }
168}
169
170pub(crate) struct DINodeCreationResult<'ll> {
171 pub di_node: &'ll DIType,
172 pub already_stored_in_typemap: bool,
173}
174
175impl<'ll> DINodeCreationResult<'ll> {
176 pub(crate) fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self {
177 DINodeCreationResult { di_node, already_stored_in_typemap }
178 }
179}
180
181#[derive(#[automatically_derived]
impl<'ll> ::core::fmt::Debug for Stub<'ll> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Stub::Struct => ::core::fmt::Formatter::write_str(f, "Struct"),
Stub::Union => ::core::fmt::Formatter::write_str(f, "Union"),
Stub::VTableTy { vtable_holder: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"VTableTy", "vtable_holder", &__self_0),
}
}
}Debug, #[automatically_derived]
impl<'ll> ::core::marker::Copy for Stub<'ll> { }Copy, #[automatically_derived]
impl<'ll> ::core::clone::Clone for Stub<'ll> {
#[inline]
fn clone(&self) -> Stub<'ll> {
let _: ::core::clone::AssertParamIsClone<&'ll DIType>;
*self
}
}Clone, #[automatically_derived]
impl<'ll> ::core::cmp::Eq for Stub<'ll> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<&'ll DIType>;
}
}Eq, #[automatically_derived]
impl<'ll> ::core::cmp::PartialEq for Stub<'ll> {
#[inline]
fn eq(&self, other: &Stub<'ll>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Stub::VTableTy { vtable_holder: __self_0 }, Stub::VTableTy {
vtable_holder: __arg1_0 }) => __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
182pub(crate) enum Stub<'ll> {
183 Struct,
184 Union,
185 VTableTy { vtable_holder: &'ll DIType },
186}
187
188pub(crate) struct StubInfo<'ll, 'tcx> {
189 metadata: &'ll DIType,
190 unique_type_id: UniqueTypeId<'tcx>,
191}
192
193impl<'ll, 'tcx> StubInfo<'ll, 'tcx> {
194 pub(super) fn new(
195 cx: &CodegenCx<'ll, 'tcx>,
196 unique_type_id: UniqueTypeId<'tcx>,
197 build: impl FnOnce(&CodegenCx<'ll, 'tcx>, &str) -> &'ll DIType,
198 ) -> StubInfo<'ll, 'tcx> {
199 let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
200 let di_node = build(cx, &unique_type_id_str);
201 StubInfo { metadata: di_node, unique_type_id }
202 }
203}
204
205pub(super) fn stub<'ll, 'tcx>(
207 cx: &CodegenCx<'ll, 'tcx>,
208 kind: Stub<'ll>,
209 unique_type_id: UniqueTypeId<'tcx>,
210 name: &str,
211 def_location: Option<DefinitionLocation<'ll>>,
212 (size, align): (Size, Align),
213 containing_scope: Option<&'ll DIScope>,
214 flags: DIFlags,
215) -> StubInfo<'ll, 'tcx> {
216 let no_elements: &[Option<&llvm::Metadata>] = &[];
217 let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
218
219 let (file_metadata, line_number) = if let Some(def_location) = def_location {
220 (def_location.0, def_location.1)
221 } else {
222 (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
223 };
224
225 let metadata = match kind {
226 Stub::Struct | Stub::VTableTy { .. } => {
227 let vtable_holder = match kind {
228 Stub::VTableTy { vtable_holder } => Some(vtable_holder),
229 _ => None,
230 };
231 unsafe {
232 llvm::LLVMDIBuilderCreateStructType(
233 DIB(cx),
234 containing_scope,
235 name.as_ptr(),
236 name.len(),
237 file_metadata,
238 line_number,
239 size.bits(),
240 align.bits() as u32,
241 flags,
242 None,
243 no_elements.as_ptr(),
244 no_elements.len() as c_uint,
245 0u32, vtable_holder,
247 unique_type_id_str.as_ptr(),
248 unique_type_id_str.len(),
249 )
250 }
251 }
252 Stub::Union => unsafe {
253 llvm::LLVMDIBuilderCreateUnionType(
254 DIB(cx),
255 containing_scope,
256 name.as_ptr(),
257 name.len(),
258 file_metadata,
259 line_number,
260 size.bits(),
261 align.bits() as u32,
262 flags,
263 no_elements.as_ptr(),
264 no_elements.len() as c_uint,
265 0u32, unique_type_id_str.as_ptr(),
267 unique_type_id_str.len(),
268 )
269 },
270 };
271 StubInfo { metadata, unique_type_id }
272}
273
274struct AdtStackPopGuard<'ll, 'tcx, 'a> {
275 cx: &'a CodegenCx<'ll, 'tcx>,
276}
277
278impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> {
279 fn drop(&mut self) {
280 debug_context(self.cx).adt_stack.borrow_mut().pop();
281 }
282}
283
284pub(super) fn build_type_with_children<'ll, 'tcx>(
291 cx: &CodegenCx<'ll, 'tcx>,
292 stub_info: StubInfo<'ll, 'tcx>,
293 members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>,
294 generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<Option<&'ll DIType>>,
295) -> DINodeCreationResult<'ll> {
296 match (&debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id),
&None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
297
298 let mut _adt_stack_pop_guard = None;
299 if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id
300 && let ty::Adt(adt_def, args) = ty.kind()
301 {
302 let def_id = adt_def.did();
303 let is_expanding_recursive = {
313 let stack = debug_context(cx).adt_stack.borrow();
314 stack
315 .iter()
316 .enumerate()
317 .rev()
318 .skip(1)
319 .filter(|(_, (ancestor_def_id, _))| def_id == *ancestor_def_id)
320 .any(|(ancestor_index, (_, ancestor_args))| {
321 args.iter()
322 .zip(ancestor_args.iter())
323 .filter_map(|(arg, ancestor_arg)| arg.as_type().zip(ancestor_arg.as_type()))
324 .any(|(arg, ancestor_arg)|
325 (arg != ancestor_arg && arg.contains(ancestor_arg))
327 && stack[ancestor_index + 1..stack.len()].iter().all(
341 |(_, intermediate_args)|
342 intermediate_args
343 .iter()
344 .filter_map(|arg| arg.as_type())
345 .any(|mid_arg| mid_arg.contains(ancestor_arg))
346 ))
347 })
348 };
349 if is_expanding_recursive {
350 return DINodeCreationResult::new(stub_info.metadata, false);
352 } else {
353 debug_context(cx).adt_stack.borrow_mut().push((def_id, args));
354 _adt_stack_pop_guard = Some(AdtStackPopGuard { cx });
355 }
356 }
357
358 debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
359
360 let members: SmallVec<_> =
361 members(cx, stub_info.metadata).into_iter().map(|node| Some(node)).collect();
362 let generics = generics(cx);
363
364 if !(members.is_empty() && generics.is_empty()) {
365 unsafe {
366 let members_array = create_DIArray(DIB(cx), &members[..]);
367 let generics_array = create_DIArray(DIB(cx), &generics[..]);
368 llvm::LLVMRustDICompositeTypeReplaceArrays(
369 DIB(cx),
370 stub_info.metadata,
371 Some(members_array),
372 Some(generics_array),
373 );
374 }
375 }
376
377 DINodeCreationResult { di_node: stub_info.metadata, already_stored_in_typemap: true }
378}