rustc_transmute/layout/
mod.rs1use std::fmt::{self, Debug};
2use std::hash::Hash;
3use std::ops::RangeInclusive;
4
5pub(crate) mod tree;
6pub(crate) use tree::Tree;
7
8pub(crate) mod dfa;
9pub(crate) use dfa::{Dfa, union};
10
11#[derive(Debug)]
12pub(crate) struct Uninhabited;
13
14#[derive(Hash, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
16pub(crate) struct Byte {
17 pub(crate) start: u16,
21 pub(crate) end: u16,
22}
23
24impl Byte {
25 const UNINIT: u16 = 256;
26
27 #[inline]
28 fn new(range: RangeInclusive<u8>) -> Self {
29 let start: u16 = (*range.start()).into();
30 let end: u16 = (*range.end()).into();
31 Byte { start, end: end + 1 }
32 }
33
34 #[inline]
35 fn from_val(val: u8) -> Self {
36 let val: u16 = val.into();
37 Byte { start: val, end: val + 1 }
38 }
39
40 #[inline]
41 fn uninit() -> Byte {
42 Byte { start: 0, end: Self::UNINIT + 1 }
43 }
44
45 #[inline]
46 fn is_empty(&self) -> bool {
47 self.start == self.end
48 }
49
50 #[inline]
51 fn contains_uninit(&self) -> bool {
52 self.start <= Self::UNINIT && Self::UNINIT < self.end
53 }
54}
55
56impl fmt::Debug for Byte {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 if self.start == Self::UNINIT && self.end == Self::UNINIT + 1 {
59 write!(f, "uninit")
60 } else if self.start <= Self::UNINIT && self.end == Self::UNINIT + 1 {
61 write!(f, "{}..{}|uninit", self.start, self.end - 1)
62 } else {
63 write!(f, "{}..{}", self.start, self.end)
64 }
65 }
66}
67
68impl From<RangeInclusive<u8>> for Byte {
69 fn from(src: RangeInclusive<u8>) -> Self {
70 Self::new(src)
71 }
72}
73
74impl From<u8> for Byte {
75 #[inline]
76 fn from(src: u8) -> Self {
77 Self::from_val(src)
78 }
79}
80
81#[derive(Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
83pub(crate) struct Reference<R, T>
84where
85 R: Region,
86 T: Type,
87{
88 pub(crate) region: R,
89 pub(crate) is_mut: bool,
90 pub(crate) referent: T,
91 pub(crate) referent_size: usize,
92 pub(crate) referent_align: usize,
93}
94
95impl<R, T> fmt::Display for Reference<R, T>
96where
97 R: Region,
98 T: Type,
99{
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 f.write_str("&")?;
102 if self.is_mut {
103 f.write_str("mut ")?;
104 }
105 self.referent.fmt(f)
106 }
107}
108
109pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone {
110 fn has_safety_invariants(&self) -> bool;
111}
112
113pub(crate) trait Region: Debug + Hash + Eq + PartialEq + Copy + Clone {}
114
115pub(crate) trait Type: Debug + Hash + Eq + PartialEq + Copy + Clone {}
116
117impl Def for ! {
118 fn has_safety_invariants(&self) -> bool {
119 unreachable!()
120 }
121}
122
123impl Region for ! {}
124
125impl Type for ! {}
126
127#[cfg(test)]
128impl Region for usize {}
129
130#[cfg(test)]
131impl Type for () {}
132
133#[cfg(feature = "rustc")]
134pub mod rustc {
135 use rustc_abi::Layout;
136 use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError};
137 use rustc_middle::ty::{self, Region, Ty};
138
139 #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
141 pub enum Def<'tcx> {
142 Adt(ty::AdtDef<'tcx>),
143 Variant(&'tcx ty::VariantDef),
144 Field(&'tcx ty::FieldDef),
145 Primitive,
146 }
147
148 impl<'tcx> super::Def for Def<'tcx> {
149 fn has_safety_invariants(&self) -> bool {
150 self != &Self::Primitive
154 }
155 }
156
157 impl<'tcx> super::Region for Region<'tcx> {}
158
159 impl<'tcx> super::Type for Ty<'tcx> {}
160
161 pub(crate) fn layout_of<'tcx>(
162 cx: LayoutCx<'tcx>,
163 ty: Ty<'tcx>,
164 ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
165 use rustc_middle::ty::layout::LayoutOf;
166 let ty = cx.tcx().erase_regions(ty);
167 cx.layout_of(ty).map(|tl| tl.layout)
168 }
169}