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 range of byte values (including an uninit byte value).
15#[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_receiver_is_total_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u16>;
    }
}Eq, #[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> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.start, &other.start)
            {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                ::core::cmp::PartialOrd::partial_cmp(&self.end, &other.end),
            cmp => cmp,
        }
    }
}PartialOrd, #[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)]
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            f.write_fmt(format_args!("uninit"))write!(f, "uninit")
60        } else if self.start <= Self::UNINIT && self.end == Self::UNINIT + 1 {
61            f.write_fmt(format_args!("{0}..{1}|uninit", self.start, self.end - 1))write!(f, "{}..{}|uninit", self.start, self.end - 1)
62        } else {
63            f.write_fmt(format_args!("{0}..{1}", self.start, self.end))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(#[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_receiver_is_total_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::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)]
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        ::core::panicking::panic("internal error: entered unreachable code")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(#[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_receiver_is_total_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::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]
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)]
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_and_anonymize_regions(ty);
167        cx.layout_of(ty).map(|tl| tl.layout)
168    }
169}