rustc_transmute/layout/
mod.rs

1use std::fmt::{self, Debug};
2use std::hash::Hash;
3
4pub(crate) mod tree;
5pub(crate) use tree::Tree;
6
7pub(crate) mod nfa;
8pub(crate) use nfa::Nfa;
9
10pub(crate) mod dfa;
11pub(crate) use dfa::Dfa;
12
13#[derive(Debug)]
14pub(crate) struct Uninhabited;
15
16/// An instance of a byte is either initialized to a particular value, or uninitialized.
17#[derive(Hash, Eq, PartialEq, Clone, Copy)]
18pub(crate) enum Byte {
19    Uninit,
20    Init(u8),
21}
22
23impl fmt::Debug for Byte {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match &self {
26            Self::Uninit => f.write_str("??u8"),
27            Self::Init(b) => write!(f, "{b:#04x}u8"),
28        }
29    }
30}
31
32pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone {
33    fn has_safety_invariants(&self) -> bool;
34}
35pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone {
36    fn min_align(&self) -> usize;
37
38    fn size(&self) -> usize;
39
40    fn is_mutable(&self) -> bool;
41}
42
43impl Def for ! {
44    fn has_safety_invariants(&self) -> bool {
45        unreachable!()
46    }
47}
48
49impl Ref for ! {
50    fn min_align(&self) -> usize {
51        unreachable!()
52    }
53    fn size(&self) -> usize {
54        unreachable!()
55    }
56    fn is_mutable(&self) -> bool {
57        unreachable!()
58    }
59}
60
61#[cfg(feature = "rustc")]
62pub mod rustc {
63    use std::fmt::{self, Write};
64
65    use rustc_abi::Layout;
66    use rustc_middle::mir::Mutability;
67    use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError};
68    use rustc_middle::ty::{self, Ty};
69
70    /// A reference in the layout.
71    #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
72    pub struct Ref<'tcx> {
73        pub lifetime: ty::Region<'tcx>,
74        pub ty: Ty<'tcx>,
75        pub mutability: Mutability,
76        pub align: usize,
77        pub size: usize,
78    }
79
80    impl<'tcx> super::Ref for Ref<'tcx> {
81        fn min_align(&self) -> usize {
82            self.align
83        }
84
85        fn size(&self) -> usize {
86            self.size
87        }
88
89        fn is_mutable(&self) -> bool {
90            match self.mutability {
91                Mutability::Mut => true,
92                Mutability::Not => false,
93            }
94        }
95    }
96    impl<'tcx> Ref<'tcx> {}
97
98    impl<'tcx> fmt::Display for Ref<'tcx> {
99        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100            f.write_char('&')?;
101            if self.mutability == Mutability::Mut {
102                f.write_str("mut ")?;
103            }
104            self.ty.fmt(f)
105        }
106    }
107
108    /// A visibility node in the layout.
109    #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
110    pub enum Def<'tcx> {
111        Adt(ty::AdtDef<'tcx>),
112        Variant(&'tcx ty::VariantDef),
113        Field(&'tcx ty::FieldDef),
114        Primitive,
115    }
116
117    impl<'tcx> super::Def for Def<'tcx> {
118        fn has_safety_invariants(&self) -> bool {
119            // Rust presently has no notion of 'unsafe fields', so for now we
120            // make the conservative assumption that everything besides
121            // primitive types carry safety invariants.
122            self != &Self::Primitive
123        }
124    }
125
126    pub(crate) fn layout_of<'tcx>(
127        cx: LayoutCx<'tcx>,
128        ty: Ty<'tcx>,
129    ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
130        use rustc_middle::ty::layout::LayoutOf;
131        let ty = cx.tcx().erase_regions(ty);
132        cx.layout_of(ty).map(|tl| tl.layout)
133    }
134}