1use std::fmt;
2use std::ops::Deref;
3
4use rustc_data_structures::intern::Interned;
5use rustc_macros::HashStable_Generic;
6
7use crate::layout::{FieldIdx, VariantIdx};
8use crate::{
9 AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
10 PointeeInfo, Primitive, Size, Variants,
11};
12
13#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for Layout<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for Layout<'a> {
#[inline]
fn clone(&self) -> Layout<'a> {
let _:
::core::clone::AssertParamIsClone<Interned<'a,
LayoutData<FieldIdx, VariantIdx>>>;
*self
}
}Clone, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for Layout<'a> {
#[inline]
fn eq(&self, other: &Layout<'a>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<'a> ::core::cmp::Eq for Layout<'a> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<Interned<'a,
LayoutData<FieldIdx, VariantIdx>>>;
}
}Eq, #[automatically_derived]
impl<'a> ::core::hash::Hash for Layout<'a> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, const _: () =
{
impl<'a, __CTX>
::rustc_data_structures::stable_hasher::HashStable<__CTX> for
Layout<'a> where __CTX: crate::HashStableContext {
#[inline]
fn hash_stable(&self, __hcx: &mut __CTX,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Layout(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable_Generic)]
16#[rustc_pass_by_value]
17pub struct Layout<'a>(pub Interned<'a, LayoutData<FieldIdx, VariantIdx>>);
18
19impl<'a> fmt::Debug for Layout<'a> {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 self.0.0.fmt(f)
23 }
24}
25
26impl<'a> Deref for Layout<'a> {
27 type Target = &'a LayoutData<FieldIdx, VariantIdx>;
28 fn deref(&self) -> &&'a LayoutData<FieldIdx, VariantIdx> {
29 &self.0.0
30 }
31}
32
33impl<'a> Layout<'a> {
34 pub fn fields(self) -> &'a FieldsShape<FieldIdx> {
35 &self.0.0.fields
36 }
37
38 pub fn variants(self) -> &'a Variants<FieldIdx, VariantIdx> {
39 &self.0.0.variants
40 }
41
42 pub fn backend_repr(self) -> BackendRepr {
43 self.0.0.backend_repr
44 }
45
46 pub fn largest_niche(self) -> Option<Niche> {
47 self.0.0.largest_niche
48 }
49
50 pub fn align(self) -> AbiAlign {
51 self.0.0.align
52 }
53
54 pub fn size(self) -> Size {
55 self.0.0.size
56 }
57
58 pub fn max_repr_align(self) -> Option<Align> {
59 self.0.0.max_repr_align
60 }
61
62 pub fn unadjusted_abi_align(self) -> Align {
63 self.0.0.unadjusted_abi_align
64 }
65}
66
67#[derive(#[automatically_derived]
impl<'a, Ty: ::core::marker::Copy> ::core::marker::Copy for
TyAndLayout<'a, Ty> {
}Copy, #[automatically_derived]
impl<'a, Ty: ::core::clone::Clone> ::core::clone::Clone for
TyAndLayout<'a, Ty> {
#[inline]
fn clone(&self) -> TyAndLayout<'a, Ty> {
TyAndLayout {
ty: ::core::clone::Clone::clone(&self.ty),
layout: ::core::clone::Clone::clone(&self.layout),
}
}
}Clone, #[automatically_derived]
impl<'a, Ty: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
TyAndLayout<'a, Ty> {
#[inline]
fn eq(&self, other: &TyAndLayout<'a, Ty>) -> bool {
self.ty == other.ty && self.layout == other.layout
}
}PartialEq, #[automatically_derived]
impl<'a, Ty: ::core::cmp::Eq> ::core::cmp::Eq for TyAndLayout<'a, Ty> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ty>;
let _: ::core::cmp::AssertParamIsEq<Layout<'a>>;
}
}Eq, #[automatically_derived]
impl<'a, Ty: ::core::hash::Hash> ::core::hash::Hash for TyAndLayout<'a, Ty> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.ty, state);
::core::hash::Hash::hash(&self.layout, state)
}
}Hash, const _: () =
{
impl<'a, Ty, __CTX>
::rustc_data_structures::stable_hasher::HashStable<__CTX> for
TyAndLayout<'a, Ty> where __CTX: crate::HashStableContext,
Ty: ::rustc_data_structures::stable_hasher::HashStable<__CTX> {
#[inline]
fn hash_stable(&self, __hcx: &mut __CTX,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
TyAndLayout { ty: ref __binding_0, layout: ref __binding_1 }
=> {
{ __binding_0.hash_stable(__hcx, __hasher); }
{ __binding_1.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable_Generic)]
75pub struct TyAndLayout<'a, Ty> {
76 pub ty: Ty,
77 pub layout: Layout<'a>,
78}
79
80impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.debug_struct("TyAndLayout")
84 .field("ty", &format_args!("{0}", self.ty)format_args!("{}", self.ty))
85 .field("layout", &self.layout)
86 .finish()
87 }
88}
89
90impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
91 type Target = &'a LayoutData<FieldIdx, VariantIdx>;
92 fn deref(&self) -> &&'a LayoutData<FieldIdx, VariantIdx> {
93 &self.layout.0.0
94 }
95}
96
97impl<'a, Ty> AsRef<LayoutData<FieldIdx, VariantIdx>> for TyAndLayout<'a, Ty> {
98 fn as_ref(&self) -> &LayoutData<FieldIdx, VariantIdx> {
99 &*self.layout.0.0
100 }
101}
102
103pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug + std::fmt::Display {
106 fn ty_and_layout_for_variant(
107 this: TyAndLayout<'a, Self>,
108 cx: &C,
109 variant_index: VariantIdx,
110 ) -> TyAndLayout<'a, Self>;
111 fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>;
112 fn ty_and_layout_pointee_info_at(
113 this: TyAndLayout<'a, Self>,
114 cx: &C,
115 offset: Size,
116 ) -> Option<PointeeInfo>;
117 fn is_adt(this: TyAndLayout<'a, Self>) -> bool;
118 fn is_never(this: TyAndLayout<'a, Self>) -> bool;
119 fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
120 fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
121 fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
122 fn is_scalable_vector(this: TyAndLayout<'a, Self>) -> bool;
123 fn is_pass_indirectly_in_non_rustic_abis_flag_set(this: TyAndLayout<'a, Self>) -> bool;
125}
126
127impl<'a, Ty> TyAndLayout<'a, Ty> {
128 pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
129 where
130 Ty: TyAbiInterface<'a, C>,
131 {
132 Ty::ty_and_layout_for_variant(self, cx, variant_index)
133 }
134
135 pub fn field<C>(self, cx: &C, i: usize) -> Self
136 where
137 Ty: TyAbiInterface<'a, C>,
138 {
139 Ty::ty_and_layout_field(self, cx, i)
140 }
141
142 pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
143 where
144 Ty: TyAbiInterface<'a, C>,
145 {
146 Ty::ty_and_layout_pointee_info_at(self, cx, offset)
147 }
148
149 pub fn is_single_fp_element<C>(self, cx: &C) -> bool
150 where
151 Ty: TyAbiInterface<'a, C>,
152 C: HasDataLayout,
153 {
154 match self.backend_repr {
155 BackendRepr::Scalar(scalar) => {
156 #[allow(non_exhaustive_omitted_patterns)] match scalar.primitive() {
Primitive::Float(Float::F32 | Float::F64) => true,
_ => false,
}matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64))
157 }
158 BackendRepr::Memory { .. } => {
159 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
160 self.field(cx, 0).is_single_fp_element(cx)
161 } else {
162 false
163 }
164 }
165 _ => false,
166 }
167 }
168
169 pub fn is_single_vector_element<C>(self, cx: &C, expected_size: Size) -> bool
170 where
171 Ty: TyAbiInterface<'a, C>,
172 C: HasDataLayout,
173 {
174 match self.backend_repr {
175 BackendRepr::SimdVector { .. } => self.size == expected_size,
176 BackendRepr::Memory { .. } => {
177 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
178 self.field(cx, 0).is_single_vector_element(cx, expected_size)
179 } else {
180 false
181 }
182 }
183 _ => false,
184 }
185 }
186
187 pub fn is_adt<C>(self) -> bool
188 where
189 Ty: TyAbiInterface<'a, C>,
190 {
191 Ty::is_adt(self)
192 }
193
194 pub fn is_never<C>(self) -> bool
195 where
196 Ty: TyAbiInterface<'a, C>,
197 {
198 Ty::is_never(self)
199 }
200
201 pub fn is_tuple<C>(self) -> bool
202 where
203 Ty: TyAbiInterface<'a, C>,
204 {
205 Ty::is_tuple(self)
206 }
207
208 pub fn is_unit<C>(self) -> bool
209 where
210 Ty: TyAbiInterface<'a, C>,
211 {
212 Ty::is_unit(self)
213 }
214
215 pub fn is_transparent<C>(self) -> bool
216 where
217 Ty: TyAbiInterface<'a, C>,
218 {
219 Ty::is_transparent(self)
220 }
221
222 pub fn is_scalable_vector<C>(self) -> bool
223 where
224 Ty: TyAbiInterface<'a, C>,
225 {
226 Ty::is_scalable_vector(self)
227 }
228
229 pub fn pass_indirectly_in_non_rustic_abis<C>(self, cx: &C) -> bool
241 where
242 Ty: TyAbiInterface<'a, C> + Copy,
243 {
244 let base = self.peel_transparent_wrappers(cx);
245 Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base)
246 }
247
248 pub fn peel_transparent_wrappers<C>(mut self, cx: &C) -> Self
253 where
254 Ty: TyAbiInterface<'a, C> + Copy,
255 {
256 while self.is_transparent()
257 && let Some((_, field)) = self.non_1zst_field(cx)
258 {
259 self = field;
260 }
261
262 self
263 }
264
265 pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
268 where
269 Ty: TyAbiInterface<'a, C> + Copy,
270 {
271 let mut found = None;
272 for field_idx in 0..self.fields.count() {
273 let field = self.field(cx, field_idx);
274 if field.is_1zst() {
275 continue;
276 }
277 if found.is_some() {
278 return None;
280 }
281 found = Some((FieldIdx::from_usize(field_idx), field));
282 }
283 found
284 }
285}