1use std::ops::{ControlFlow, RangeInclusive};
2
3use super::{Byte, Def, Reference, Region, Type};
4
5#[cfg(test)]
6mod tests;
7
8#[derive(#[automatically_derived]
impl<D: ::core::clone::Clone, R: ::core::clone::Clone,
T: ::core::clone::Clone> ::core::clone::Clone for Tree<D, R, T> where
D: Def, R: Region, T: Type {
#[inline]
fn clone(&self) -> Tree<D, R, T> {
match self {
Tree::Seq(__self_0) =>
Tree::Seq(::core::clone::Clone::clone(__self_0)),
Tree::Alt(__self_0) =>
Tree::Alt(::core::clone::Clone::clone(__self_0)),
Tree::Def(__self_0) =>
Tree::Def(::core::clone::Clone::clone(__self_0)),
Tree::Ref(__self_0) =>
Tree::Ref(::core::clone::Clone::clone(__self_0)),
Tree::Byte(__self_0) =>
Tree::Byte(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl<D: ::core::fmt::Debug, R: ::core::fmt::Debug, T: ::core::fmt::Debug>
::core::fmt::Debug for Tree<D, R, T> where D: Def, R: Region, T: Type {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Tree::Seq(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Seq",
&__self_0),
Tree::Alt(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Alt",
&__self_0),
Tree::Def(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Def",
&__self_0),
Tree::Ref(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ref",
&__self_0),
Tree::Byte(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Byte",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl<D: ::core::hash::Hash, R: ::core::hash::Hash, T: ::core::hash::Hash>
::core::hash::Hash for Tree<D, R, T> where D: Def, R: Region, T: Type {
#[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 {
Tree::Seq(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Tree::Alt(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Tree::Def(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Tree::Ref(__self_0) => ::core::hash::Hash::hash(__self_0, state),
Tree::Byte(__self_0) => ::core::hash::Hash::hash(__self_0, state),
}
}
}Hash, #[automatically_derived]
impl<D: ::core::cmp::PartialEq, R: ::core::cmp::PartialEq,
T: ::core::cmp::PartialEq> ::core::marker::StructuralPartialEq for
Tree<D, R, T> where D: Def, R: Region, T: Type {
}
#[automatically_derived]
impl<D: ::core::cmp::PartialEq, R: ::core::cmp::PartialEq,
T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for Tree<D, R, T> where
D: Def, R: Region, T: Type {
#[inline]
fn eq(&self, other: &Tree<D, R, T>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Tree::Seq(__self_0), Tree::Seq(__arg1_0)) =>
__self_0 == __arg1_0,
(Tree::Alt(__self_0), Tree::Alt(__arg1_0)) =>
__self_0 == __arg1_0,
(Tree::Def(__self_0), Tree::Def(__arg1_0)) =>
__self_0 == __arg1_0,
(Tree::Ref(__self_0), Tree::Ref(__arg1_0)) =>
__self_0 == __arg1_0,
(Tree::Byte(__self_0), Tree::Byte(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<D: ::core::cmp::Eq, R: ::core::cmp::Eq, T: ::core::cmp::Eq>
::core::cmp::Eq for Tree<D, R, T> where D: Def, R: Region, T: Type {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Vec<Self>>;
let _: ::core::cmp::AssertParamIsEq<Vec<Self>>;
let _: ::core::cmp::AssertParamIsEq<D>;
let _: ::core::cmp::AssertParamIsEq<Reference<R, T>>;
let _: ::core::cmp::AssertParamIsEq<Byte>;
}
}Eq)]
26pub(crate) enum Tree<D, R, T>
27where
28 D: Def,
29 R: Region,
30 T: Type,
31{
32 Seq(Vec<Self>),
34 Alt(Vec<Self>),
36 Def(D),
38 Ref(Reference<R, T>),
40 Byte(Byte),
42}
43
44#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Endian {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self { Endian::Little => "Little", Endian::Big => "Big", })
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for Endian { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Endian { }
#[automatically_derived]
impl ::core::clone::Clone for Endian {
#[inline]
fn clone(&self) -> Endian { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Endian { }Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Endian { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Endian {
#[inline]
fn eq(&self, other: &Endian) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
45pub(crate) enum Endian {
46 Little,
47 Big,
48}
49
50#[cfg(feature = "rustc")]
51impl From<rustc_abi::Endian> for Endian {
52 fn from(order: rustc_abi::Endian) -> Endian {
53 match order {
54 rustc_abi::Endian::Little => Endian::Little,
55 rustc_abi::Endian::Big => Endian::Big,
56 }
57 }
58}
59
60impl<D, R, T> Tree<D, R, T>
61where
62 D: Def,
63 R: Region,
64 T: Type,
65{
66 pub(crate) fn def(def: D) -> Self {
68 Self::Def(def)
69 }
70
71 pub(crate) fn uninhabited() -> Self {
73 Self::Alt(::alloc::vec::Vec::new()vec![])
74 }
75
76 pub(crate) fn unit() -> Self {
78 Self::Seq(Vec::new())
79 }
80
81 pub(crate) fn uninit() -> Self {
83 Self::Byte(Byte::uninit())
84 }
85
86 pub(crate) fn bool() -> Self {
88 Self::byte(0x00..=0x01)
89 }
90
91 pub(crate) fn u8() -> Self {
93 Self::byte(0x00..=0xFF)
94 }
95
96 pub(crate) fn char(order: Endian) -> Self {
98 const _0: RangeInclusive<u8> = 0..=0;
109 const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
110 let x = Self::from_big_endian(order, [_0, _0, 0x00..=0xD7, BYTE]);
111 let y = Self::from_big_endian(order, [_0, _0, 0xE0..=0xFF, BYTE]);
112 let z = Self::from_big_endian(order, [_0, 0x01..=0x10, BYTE, BYTE]);
113 Self::alt([x, y, z])
114 }
115
116 #[allow(dead_code)]
118 pub(crate) fn nonzero(width_in_bytes: u64) -> Self {
119 const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
120 const NONZERO: RangeInclusive<u8> = 0x01..=0xFF;
121
122 (0..width_in_bytes)
123 .map(|nz_idx| {
124 (0..width_in_bytes)
125 .map(|pos| Self::byte(if pos == nz_idx { NONZERO } else { BYTE }))
126 .fold(Self::unit(), Self::then)
127 })
128 .fold(Self::uninhabited(), Self::or)
129 }
130
131 pub(crate) fn bytes<const N: usize, B: Into<Byte>>(bytes: [B; N]) -> Self {
132 Self::seq(bytes.map(B::into).map(Self::Byte))
133 }
134
135 pub(crate) fn byte(byte: impl Into<Byte>) -> Self {
136 Self::Byte(byte.into())
137 }
138
139 pub(crate) fn number(width_in_bytes: u64) -> Self {
141 Self::Seq(::alloc::vec::from_elem(Self::u8(), width_in_bytes.try_into().unwrap())vec![Self::u8(); width_in_bytes.try_into().unwrap()])
142 }
143
144 pub(crate) fn padding(width_in_bytes: usize) -> Self {
148 Self::Seq(::alloc::vec::from_elem(Self::uninit(), width_in_bytes)vec![Self::uninit(); width_in_bytes])
149 }
150
151 pub(crate) fn prune<F>(self, f: &F) -> Tree<!, R, T>
158 where
159 F: Fn(D) -> bool,
160 {
161 match self {
162 Self::Seq(elts) => match elts.into_iter().map(|elt| elt.prune(f)).try_fold(
163 Tree::unit(),
164 |elts, elt| {
165 if elt == Tree::uninhabited() {
166 ControlFlow::Break(Tree::uninhabited())
167 } else {
168 ControlFlow::Continue(elts.then(elt))
169 }
170 },
171 ) {
172 ControlFlow::Break(node) | ControlFlow::Continue(node) => node,
173 },
174 Self::Alt(alts) => alts
175 .into_iter()
176 .map(|alt| alt.prune(f))
177 .fold(Tree::uninhabited(), |alts, alt| alts.or(alt)),
178 Self::Byte(b) => Tree::Byte(b),
179 Self::Ref(r) => Tree::Ref(r),
180 Self::Def(d) => {
181 if f(d) {
182 Tree::uninhabited()
183 } else {
184 Tree::unit()
185 }
186 }
187 }
188 }
189
190 pub(crate) fn is_inhabited(&self) -> bool {
192 match self {
193 Self::Seq(elts) => elts.into_iter().all(|elt| elt.is_inhabited()),
194 Self::Alt(alts) => alts.into_iter().any(|alt| alt.is_inhabited()),
195 Self::Byte(..) | Self::Ref(..) | Self::Def(..) => true,
196 }
197 }
198
199 pub(crate) fn from_big_endian<const N: usize, B: Into<Byte>>(
205 order: Endian,
206 mut bytes: [B; N],
207 ) -> Self {
208 if order == Endian::Little {
209 (&mut bytes[..]).reverse();
210 }
211
212 Self::bytes(bytes)
213 }
214
215 pub(crate) fn seq<const N: usize>(trees: [Tree<D, R, T>; N]) -> Self {
218 trees.into_iter().fold(Tree::unit(), Self::then)
219 }
220
221 pub(crate) fn alt<const N: usize>(trees: [Tree<D, R, T>; N]) -> Self {
224 trees.into_iter().fold(Tree::uninhabited(), Self::or)
225 }
226
227 pub(crate) fn then(self, other: Self) -> Self {
229 match (self, other) {
230 (Self::Seq(elts), other) | (other, Self::Seq(elts)) if elts.len() == 0 => other,
231 (Self::Seq(mut lhs), Self::Seq(mut rhs)) => {
232 lhs.append(&mut rhs);
233 Self::Seq(lhs)
234 }
235 (Self::Seq(mut lhs), rhs) => {
236 lhs.push(rhs);
237 Self::Seq(lhs)
238 }
239 (lhs, Self::Seq(mut rhs)) => {
240 rhs.insert(0, lhs);
241 Self::Seq(rhs)
242 }
243 (lhs, rhs) => Self::Seq(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[lhs, rhs]))vec![lhs, rhs]),
244 }
245 }
246
247 pub(crate) fn or(self, other: Self) -> Self {
249 match (self, other) {
250 (Self::Alt(alts), other) | (other, Self::Alt(alts)) if alts.len() == 0 => other,
251 (Self::Alt(mut lhs), Self::Alt(rhs)) => {
252 lhs.extend(rhs);
253 Self::Alt(lhs)
254 }
255 (Self::Alt(mut alts), alt) | (alt, Self::Alt(mut alts)) => {
256 alts.push(alt);
257 Self::Alt(alts)
258 }
259 (lhs, rhs) => Self::Alt(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[lhs, rhs]))vec![lhs, rhs]),
260 }
261 }
262}
263
264#[cfg(feature = "rustc")]
265pub(crate) mod rustc {
266 use rustc_abi::{
267 FieldIdx, FieldsShape, Layout, Size, TagEncoding, TyAndLayout, VariantIdx, Variants,
268 };
269 use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError};
270 use rustc_middle::ty::{
271 self, AdtDef, AdtKind, List, Region, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
272 };
273 use rustc_span::ErrorGuaranteed;
274
275 use super::Tree;
276 use crate::layout::Reference;
277 use crate::layout::rustc::{Def, layout_of};
278
279 #[derive(#[automatically_derived]
impl ::core::fmt::Debug for Err {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Err::NotYetSupported =>
::core::fmt::Formatter::write_str(f, "NotYetSupported"),
Err::UnknownLayout =>
::core::fmt::Formatter::write_str(f, "UnknownLayout"),
Err::SizeOverflow =>
::core::fmt::Formatter::write_str(f, "SizeOverflow"),
Err::TypeError(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TypeError", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for Err { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Err { }
#[automatically_derived]
impl ::core::clone::Clone for Err {
#[inline]
fn clone(&self) -> Err {
let _: ::core::clone::AssertParamIsClone<ErrorGuaranteed>;
*self
}
}Clone)]
280 pub(crate) enum Err {
281 NotYetSupported,
283 UnknownLayout,
285 SizeOverflow,
287 TypeError(ErrorGuaranteed),
288 }
289
290 impl<'tcx> From<&LayoutError<'tcx>> for Err {
291 fn from(err: &LayoutError<'tcx>) -> Self {
292 match err {
293 LayoutError::Unknown(..)
294 | LayoutError::ReferencesError(..)
295 | LayoutError::TooGeneric(..)
296 | LayoutError::InvalidSimd { .. }
297 | LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
298 LayoutError::SizeOverflow(..) => Self::SizeOverflow,
299 }
300 }
301 }
302
303 impl<'tcx> Tree<Def<'tcx>, Region<'tcx>, Ty<'tcx>> {
304 pub(crate) fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx>) -> Result<Self, Err> {
305 use rustc_abi::HasDataLayout;
306 let layout = layout_of(cx, ty)?;
307
308 if let Err(e) = ty.error_reported() {
309 return Err(Err::TypeError(e));
310 }
311
312 let target = cx.data_layout();
313 let pointer_size = target.pointer_size();
314
315 match ty.kind() {
316 ty::Bool => Ok(Self::bool()),
317
318 ty::Float(nty) => {
319 let width = nty.bit_width() / 8;
320 Ok(Self::number(width.try_into().unwrap()))
321 }
322
323 ty::Int(nty) => {
324 let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
325 Ok(Self::number(width.try_into().unwrap()))
326 }
327
328 ty::Uint(nty) => {
329 let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
330 Ok(Self::number(width.try_into().unwrap()))
331 }
332
333 ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx),
334
335 ty::Array(inner_ty, _len) => {
336 let FieldsShape::Array { stride, count } = &layout.fields else {
337 return Err(Err::NotYetSupported);
338 };
339 let inner_layout = layout_of(cx, *inner_ty)?;
340 {
match (&*stride, &inner_layout.size) {
(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!(*stride, inner_layout.size);
341 let elt = Tree::from_ty(*inner_ty, cx)?;
342 Ok(std::iter::repeat_n(elt, *count as usize)
343 .fold(Tree::unit(), |tree, elt| tree.then(elt)))
344 }
345
346 ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() {
347 AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx),
348 AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx),
349 AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx),
350 },
351
352 ty::Ref(region, ty, mutability) => {
353 let layout = layout_of(cx, *ty)?;
354 let referent_align = layout.align.bytes_usize();
355 let referent_size = layout.size.bytes_usize();
356
357 Ok(Tree::Ref(Reference {
358 region: *region,
359 is_mut: mutability.is_mut(),
360 referent: *ty,
361 referent_align,
362 referent_size,
363 }))
364 }
365
366 ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
367
368 _ => Err(Err::NotYetSupported),
369 }
370 }
371
372 fn from_tuple(
374 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
375 members: &'tcx List<Ty<'tcx>>,
376 cx: LayoutCx<'tcx>,
377 ) -> Result<Self, Err> {
378 match &layout.fields {
379 FieldsShape::Primitive => {
380 {
match (&members.len(), &1) {
(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!(members.len(), 1);
381 let inner_ty = members[0];
382 Self::from_ty(inner_ty, cx)
383 }
384 FieldsShape::Arbitrary { offsets, .. } => {
385 {
match (&offsets.len(), &members.len()) {
(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!(offsets.len(), members.len());
386 Self::from_variant(Def::Primitive, None, (ty, layout), layout.size, cx)
387 }
388 FieldsShape::Array { .. } | FieldsShape::Union(_) => Err(Err::NotYetSupported),
389 }
390 }
391
392 fn from_struct(
398 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
399 def: AdtDef<'tcx>,
400 cx: LayoutCx<'tcx>,
401 ) -> Result<Self, Err> {
402 if !def.is_struct() {
::core::panicking::panic("assertion failed: def.is_struct()")
};assert!(def.is_struct());
403 let def = Def::Adt(def);
404 Self::from_variant(def, None, (ty, layout), layout.size, cx)
405 }
406
407 fn from_enum(
413 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
414 def: AdtDef<'tcx>,
415 cx: LayoutCx<'tcx>,
416 ) -> Result<Self, Err> {
417 if !def.is_enum() {
::core::panicking::panic("assertion failed: def.is_enum()")
};assert!(def.is_enum());
418
419 let layout_of_variant = |index, encoding: Option<_>| -> Result<Self, Err> {
421 let variant_layout = ty_variant(cx, (ty, layout), index);
422 if variant_layout.is_uninhabited() {
423 return Ok(Self::uninhabited());
424 }
425 let tag = cx.tcx().tag_for_variant(
426 cx.typing_env.as_query_input((cx.tcx().erase_and_anonymize_regions(ty), index)),
427 );
428 let variant_def = Def::Variant(def.variant(index));
429 Self::from_variant(
430 variant_def,
431 tag.map(|tag| (tag, index, encoding.unwrap())),
432 (ty, variant_layout),
433 layout.size,
434 cx,
435 )
436 };
437
438 match *layout.variants() {
439 Variants::Empty => Ok(Self::uninhabited()),
440 Variants::Single { index } => {
441 layout_of_variant(index, None)
444 }
445 Variants::Multiple { tag: _, tag_encoding, tag_field, .. } => {
446 {
match (&tag_field, &FieldIdx::ZERO) {
(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!(tag_field, FieldIdx::ZERO);
453
454 let variants = def.discriminants(cx.tcx()).try_fold(
455 Self::uninhabited(),
456 |variants, (idx, _discriminant)| {
457 let variant = layout_of_variant(idx, Some(tag_encoding))?;
458 Result::<Self, Err>::Ok(variants.or(variant))
459 },
460 )?;
461
462 Ok(Self::def(Def::Adt(def)).then(variants))
463 }
464 }
465 }
466
467 fn from_variant(
477 def: Def<'tcx>,
478 tag: Option<(ScalarInt, VariantIdx, TagEncoding<VariantIdx>)>,
479 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
480 total_size: Size,
481 cx: LayoutCx<'tcx>,
482 ) -> Result<Self, Err> {
483 let FieldsShape::Arbitrary { offsets, in_memory_order } = layout.fields() else {
486 return Err(Err::NotYetSupported);
487 };
488
489 if !(layout.size <= total_size) {
::core::panicking::panic("assertion failed: layout.size <= total_size")
};assert!(layout.size <= total_size);
493
494 let mut size = Size::ZERO;
495 let mut struct_tree = Self::def(def);
496
497 if let Some((tag, index, encoding)) = &tag {
499 match encoding {
500 TagEncoding::Direct => {
501 size += tag.size();
502 }
503 TagEncoding::Niche { niche_variants, .. } => {
504 if !niche_variants.contains(index) {
505 size += tag.size();
506 }
507 }
508 }
509 struct_tree = struct_tree.then(Self::from_tag(*tag, cx.tcx()));
510 }
511
512 for &field_idx in in_memory_order.iter() {
514 let padding_needed = offsets[field_idx] - size;
516 let padding = Self::padding(padding_needed.bytes_usize());
517
518 let field_ty = ty_field(cx, (ty, layout), field_idx);
519 let field_layout = layout_of(cx, field_ty)?;
520 let field_tree = Self::from_ty(field_ty, cx)?;
521
522 struct_tree = struct_tree.then(padding).then(field_tree);
523
524 size += padding_needed + field_layout.size;
525 }
526
527 let padding_needed = total_size - size;
529 let trailing_padding = Self::padding(padding_needed.bytes_usize());
530
531 Ok(struct_tree.then(trailing_padding))
532 }
533
534 fn from_tag(tag: ScalarInt, tcx: TyCtxt<'tcx>) -> Self {
536 use rustc_abi::Endian;
537 let size = tag.size();
538 let bits = tag.to_bits(size);
539 let bytes: [u8; 16];
540 let bytes = match tcx.data_layout.endian {
541 Endian::Little => {
542 bytes = bits.to_le_bytes();
543 &bytes[..size.bytes_usize()]
544 }
545 Endian::Big => {
546 bytes = bits.to_be_bytes();
547 &bytes[bytes.len() - size.bytes_usize()..]
548 }
549 };
550 Self::Seq(bytes.iter().map(|&b| Self::byte(b)).collect())
551 }
552
553 fn from_union(
559 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
560 def: AdtDef<'tcx>,
561 cx: LayoutCx<'tcx>,
562 ) -> Result<Self, Err> {
563 if !def.is_union() {
::core::panicking::panic("assertion failed: def.is_union()")
};assert!(def.is_union());
564
565 let FieldsShape::Union(_fields) = layout.fields() else {
568 return Err(Err::NotYetSupported);
569 };
570
571 let fields = &def.non_enum_variant().fields;
572 let fields = fields.iter_enumerated().try_fold(
573 Self::uninhabited(),
574 |fields, (idx, _field_def)| {
575 let field_ty = ty_field(cx, (ty, layout), idx);
576 let field_layout = layout_of(cx, field_ty)?;
577 let field = Self::from_ty(field_ty, cx)?;
578 let trailing_padding_needed = layout.size - field_layout.size;
579 let trailing_padding = Self::padding(trailing_padding_needed.bytes_usize());
580 let field_and_padding = field.then(trailing_padding);
581 Result::<Self, Err>::Ok(fields.or(field_and_padding))
582 },
583 )?;
584
585 Ok(Self::def(Def::Adt(def)).then(fields))
586 }
587 }
588
589 fn ty_field<'tcx>(
590 cx: LayoutCx<'tcx>,
591 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
592 i: FieldIdx,
593 ) -> Ty<'tcx> {
594 match ty.kind() {
599 ty::Adt(def, args) => {
600 match layout.variants {
601 Variants::Single { index } => {
602 let field = &def.variant(index).fields[i];
603 field.ty(cx.tcx(), args).skip_norm_wip()
604 }
605 Variants::Empty => {
::core::panicking::panic_fmt(format_args!("there is no field in Variants::Empty types"));
}panic!("there is no field in Variants::Empty types"),
606 Variants::Multiple { tag, .. } => {
608 {
match (&i.as_usize(), &0) {
(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!(i.as_usize(), 0);
609 ty::layout::PrimitiveExt::to_ty(&tag.primitive(), cx.tcx())
610 }
611 }
612 }
613 ty::Tuple(fields) => fields[i.as_usize()],
614 kind => {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("only a subset of `Ty::ty_and_layout_field`\'s functionality is implemented. implementation needed for {0:?}",
kind)));
}unimplemented!(
615 "only a subset of `Ty::ty_and_layout_field`'s functionality is implemented. implementation needed for {:?}",
616 kind
617 ),
618 }
619 }
620
621 fn ty_variant<'tcx>(
622 cx: LayoutCx<'tcx>,
623 (ty, layout): (Ty<'tcx>, Layout<'tcx>),
624 i: VariantIdx,
625 ) -> Layout<'tcx> {
626 let ty = cx.tcx().erase_and_anonymize_regions(ty);
627 TyAndLayout { ty, layout }.for_variant(&cx, i).layout
628 }
629}