Skip to main content

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(#[automatically_derived]
impl ::core::fmt::Debug for Uninhabited {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Uninhabited")
    }
}Debug)]
12pub(crate) struct Uninhabited;
13
14/// A half-open range of byte values, which may include an uninitialized byte.
15///
16/// The range is `[start, end)`. Values `0..=255` represent initialized bytes,
17/// and `256` represents an uninitialized byte. A range containing that value
18/// therefore has an exclusive upper bound of `257`.
19#[derive(#[automatically_derived]
impl ::core::hash::Hash for Byte {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.start, state);
        ::core::hash::Hash::hash(&self.end, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::Eq for Byte {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u16>;
    }
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Byte { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Byte {
    #[inline]
    fn eq(&self, other: &Byte) -> bool {
        self.start == other.start && self.end == other.end
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Byte {
    #[inline]
    fn cmp(&self, other: &Byte) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.start, &other.start) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.end, &other.end),
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Byte {
    #[inline]
    fn partial_cmp(&self, other: &Byte)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Byte { }
#[automatically_derived]
impl ::core::clone::Clone for Byte {
    #[inline]
    fn clone(&self) -> Byte {
        let _: ::core::clone::AssertParamIsClone<u16>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Byte { }Copy)]
20pub(crate) struct Byte {
21    // Store the endpoints separately because `Range` is not `Copy`.
22    pub(crate) start: u16,
23    pub(crate) end: u16,
24}
25
26impl Byte {
27    const UNINIT: u16 = 256;
28
29    #[inline]
30    fn new(range: RangeInclusive<u8>) -> Self {
31        let start: u16 = (*range.start()).into();
32        let end: u16 = (*range.end()).into();
33        Byte { start, end: end + 1 }
34    }
35
36    #[inline]
37    fn from_val(val: u8) -> Self {
38        let val: u16 = val.into();
39        Byte { start: val, end: val + 1 }
40    }
41
42    /// A byte that may be initialized to any value or uninitialized.
43    #[inline]
44    fn uninit() -> Byte {
45        Byte { start: 0, end: Self::UNINIT + 1 }
46    }
47
48    #[inline]
49    fn is_empty(&self) -> bool {
50        self.start == self.end
51    }
52
53    #[inline]
54    fn contains_uninit(&self) -> bool {
55        self.start <= Self::UNINIT && Self::UNINIT < self.end
56    }
57}
58
59impl fmt::Debug for Byte {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        if self.start == Self::UNINIT && self.end == Self::UNINIT + 1 {
62            f.write_fmt(format_args!("uninit"))write!(f, "uninit")
63        } else if self.start <= Self::UNINIT && self.end == Self::UNINIT + 1 {
64            f.write_fmt(format_args!("{0}..{1}|uninit", self.start, self.end - 1))write!(f, "{}..{}|uninit", self.start, self.end - 1)
65        } else {
66            f.write_fmt(format_args!("{0}..{1}", self.start, self.end))write!(f, "{}..{}", self.start, self.end)
67        }
68    }
69}
70
71impl From<RangeInclusive<u8>> for Byte {
72    fn from(src: RangeInclusive<u8>) -> Self {
73        Self::new(src)
74    }
75}
76
77impl From<u8> for Byte {
78    #[inline]
79    fn from(src: u8) -> Self {
80        Self::from_val(src)
81    }
82}
83
84/// A reference, i.e., `&'region T` or `&'region mut T`.
85#[derive(#[automatically_derived]
impl<R: ::core::fmt::Debug, T: ::core::fmt::Debug> ::core::fmt::Debug for
    Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f, "Reference",
            "region", &self.region, "is_mut", &self.is_mut, "referent",
            &self.referent, "referent_size", &self.referent_size,
            "referent_align", &&self.referent_align)
    }
}Debug, #[automatically_derived]
impl<R: ::core::hash::Hash, T: ::core::hash::Hash> ::core::hash::Hash for
    Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.region, state);
        ::core::hash::Hash::hash(&self.is_mut, state);
        ::core::hash::Hash::hash(&self.referent, state);
        ::core::hash::Hash::hash(&self.referent_size, state);
        ::core::hash::Hash::hash(&self.referent_align, state)
    }
}Hash, #[automatically_derived]
impl<R: ::core::cmp::Eq, T: ::core::cmp::Eq> ::core::cmp::Eq for
    Reference<R, T> where R: Region, T: Type {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<R>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<T>;
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl<R: ::core::cmp::PartialEq, T: ::core::cmp::PartialEq>
    ::core::marker::StructuralPartialEq for Reference<R, T> where R: Region,
    T: Type {
}
#[automatically_derived]
impl<R: ::core::cmp::PartialEq, T: ::core::cmp::PartialEq>
    ::core::cmp::PartialEq for Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn eq(&self, other: &Reference<R, T>) -> bool {
        self.is_mut == other.is_mut && self.region == other.region &&
                    self.referent == other.referent &&
                self.referent_size == other.referent_size &&
            self.referent_align == other.referent_align
    }
}PartialEq, #[automatically_derived]
impl<R: ::core::cmp::Ord, T: ::core::cmp::Ord> ::core::cmp::Ord for
    Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn cmp(&self, other: &Reference<R, T>) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.region, &other.region) {
            ::core::cmp::Ordering::Equal =>
                match ::core::cmp::Ord::cmp(&self.is_mut, &other.is_mut) {
                    ::core::cmp::Ordering::Equal =>
                        match ::core::cmp::Ord::cmp(&self.referent, &other.referent)
                            {
                            ::core::cmp::Ordering::Equal =>
                                match ::core::cmp::Ord::cmp(&self.referent_size,
                                        &other.referent_size) {
                                    ::core::cmp::Ordering::Equal =>
                                        ::core::cmp::Ord::cmp(&self.referent_align,
                                            &other.referent_align),
                                    cmp => cmp,
                                },
                            cmp => cmp,
                        },
                    cmp => cmp,
                },
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl<R: ::core::cmp::PartialOrd, T: ::core::cmp::PartialOrd>
    ::core::cmp::PartialOrd for Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn partial_cmp(&self, other: &Reference<R, T>)
        -> ::core::option::Option<::core::cmp::Ordering> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.region,
                &other.region) {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                match ::core::cmp::PartialOrd::partial_cmp(&self.is_mut,
                        &other.is_mut) {
                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
                        =>
                        match ::core::cmp::PartialOrd::partial_cmp(&self.referent,
                                &other.referent) {
                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
                                =>
                                match ::core::cmp::PartialOrd::partial_cmp(&self.referent_size,
                                        &other.referent_size) {
                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
                                        =>
                                        ::core::cmp::PartialOrd::partial_cmp(&self.referent_align,
                                            &other.referent_align),
                                    cmp => cmp,
                                },
                            cmp => cmp,
                        },
                    cmp => cmp,
                },
            cmp => cmp,
        }
    }
}PartialOrd, #[automatically_derived]
impl<R: ::core::clone::Clone, T: ::core::clone::Clone> ::core::clone::Clone
    for Reference<R, T> where R: Region, T: Type {
    #[inline]
    fn clone(&self) -> Reference<R, T> {
        Reference {
            region: ::core::clone::Clone::clone(&self.region),
            is_mut: ::core::clone::Clone::clone(&self.is_mut),
            referent: ::core::clone::Clone::clone(&self.referent),
            referent_size: ::core::clone::Clone::clone(&self.referent_size),
            referent_align: ::core::clone::Clone::clone(&self.referent_align),
        }
    }
}Clone, #[automatically_derived]
impl<R: ::core::marker::Copy, T: ::core::marker::Copy> ::core::marker::Copy
    for Reference<R, T> where R: Region, T: Type {
}Copy)]
86pub(crate) struct Reference<R, T>
87where
88    R: Region,
89    T: Type,
90{
91    pub(crate) region: R,
92    pub(crate) is_mut: bool,
93    pub(crate) referent: T,
94    pub(crate) referent_size: usize,
95    pub(crate) referent_align: usize,
96}
97
98impl<R, T> fmt::Display for Reference<R, T>
99where
100    R: Region,
101    T: Type,
102{
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        f.write_str("&")?;
105        if self.is_mut {
106            f.write_str("mut ")?;
107        }
108        self.referent.fmt(f)
109    }
110}
111
112pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone {
113    fn has_safety_invariants(&self) -> bool;
114}
115
116pub(crate) trait Region: Debug + Hash + Eq + PartialEq + Copy + Clone {}
117
118pub(crate) trait Type: Debug + Hash + Eq + PartialEq + Copy + Clone {}
119
120impl Def for ! {
121    fn has_safety_invariants(&self) -> bool {
122        ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
123    }
124}
125
126impl Region for ! {}
127
128impl Type for ! {}
129
130#[cfg(test)]
131impl Region for usize {}
132
133#[cfg(test)]
134impl Type for () {}
135
136#[cfg(feature = "rustc")]
137pub mod rustc {
138    use rustc_abi::Layout;
139    use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError};
140    use rustc_middle::ty::{self, Region, Ty};
141
142    /// A layout annotation used to check for safety invariants during pruning.
143    #[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for Def<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Def::Adt(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Adt",
                    &__self_0),
            Def::Variant(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Variant", &__self_0),
            Def::Field(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Field",
                    &__self_0),
            Def::Primitive =>
                ::core::fmt::Formatter::write_str(f, "Primitive"),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for Def<'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 {
            Def::Adt(__self_0) => ::core::hash::Hash::hash(__self_0, state),
            Def::Variant(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            Def::Field(__self_0) => ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Def<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::AdtDef<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<&'tcx ty::VariantDef>;
        let _: ::core::cmp::AssertParamIsEq<&'tcx ty::FieldDef>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for Def<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Def<'tcx> {
    #[inline]
    fn eq(&self, other: &Def<'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) {
                (Def::Adt(__self_0), Def::Adt(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Def::Variant(__self_0), Def::Variant(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Def::Field(__self_0), Def::Field(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for Def<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Def<'tcx> {
    #[inline]
    fn clone(&self) -> Def<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::AdtDef<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<&'tcx ty::VariantDef>;
        let _: ::core::clone::AssertParamIsClone<&'tcx ty::FieldDef>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for Def<'tcx> { }Copy)]
144    pub enum Def<'tcx> {
145        Adt(ty::AdtDef<'tcx>),
146        Variant(&'tcx ty::VariantDef),
147        Field(&'tcx ty::FieldDef),
148        Primitive,
149    }
150
151    impl<'tcx> super::Def for Def<'tcx> {
152        fn has_safety_invariants(&self) -> bool {
153            // Conservatively treat every ADT, variant, and field definition as
154            // potentially carrying safety invariants. This check does not
155            // inspect `unsafe` field annotations.
156            self != &Self::Primitive
157        }
158    }
159
160    impl<'tcx> super::Region for Region<'tcx> {}
161
162    impl<'tcx> super::Type for Ty<'tcx> {}
163
164    pub(crate) fn layout_of<'tcx>(
165        cx: LayoutCx<'tcx>,
166        ty: Ty<'tcx>,
167    ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
168        use rustc_middle::ty::layout::LayoutOf;
169        let ty = cx.tcx().erase_and_anonymize_regions(ty);
170        cx.layout_of(ty).map(|tl| tl.layout)
171    }
172}