rustc_transmute/layout/
mod.rs

1use 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/// A range of byte values (including an uninit byte value).
15#[derive(Hash, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
16pub(crate) struct Byte {
17    // An inclusive-exclusive range. We use this instead of `Range` because `Range: !Copy`.
18    //
19    // Uninit byte value is represented by 256.
20    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/// A reference, i.e., `&'region T` or `&'region mut T`.
82#[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    /// A visibility node in the layout.
140    #[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            // Rust presently has no notion of 'unsafe fields', so for now we
151            // make the conservative assumption that everything besides
152            // primitive types carry safety invariants.
153            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}