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
81pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone {
82 fn has_safety_invariants(&self) -> bool;
83}
84pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone {
85 fn min_align(&self) -> usize;
86
87 fn size(&self) -> usize;
88
89 fn is_mutable(&self) -> bool;
90}
91
92impl Def for ! {
93 fn has_safety_invariants(&self) -> bool {
94 unreachable!()
95 }
96}
97
98impl Ref for ! {
99 fn min_align(&self) -> usize {
100 unreachable!()
101 }
102 fn size(&self) -> usize {
103 unreachable!()
104 }
105 fn is_mutable(&self) -> bool {
106 unreachable!()
107 }
108}
109
110#[cfg(test)]
111impl<const N: usize> Ref for [(); N] {
112 fn min_align(&self) -> usize {
113 N
114 }
115
116 fn size(&self) -> usize {
117 N
118 }
119
120 fn is_mutable(&self) -> bool {
121 false
122 }
123}
124
125#[cfg(feature = "rustc")]
126pub mod rustc {
127 use std::fmt::{self, Write};
128
129 use rustc_abi::Layout;
130 use rustc_middle::mir::Mutability;
131 use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError};
132 use rustc_middle::ty::{self, Ty};
133
134 #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
136 pub struct Ref<'tcx> {
137 pub lifetime: ty::Region<'tcx>,
138 pub ty: Ty<'tcx>,
139 pub mutability: Mutability,
140 pub align: usize,
141 pub size: usize,
142 }
143
144 impl<'tcx> super::Ref for Ref<'tcx> {
145 fn min_align(&self) -> usize {
146 self.align
147 }
148
149 fn size(&self) -> usize {
150 self.size
151 }
152
153 fn is_mutable(&self) -> bool {
154 match self.mutability {
155 Mutability::Mut => true,
156 Mutability::Not => false,
157 }
158 }
159 }
160 impl<'tcx> Ref<'tcx> {}
161
162 impl<'tcx> fmt::Display for Ref<'tcx> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.write_char('&')?;
165 if self.mutability == Mutability::Mut {
166 f.write_str("mut ")?;
167 }
168 self.ty.fmt(f)
169 }
170 }
171
172 #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
174 pub enum Def<'tcx> {
175 Adt(ty::AdtDef<'tcx>),
176 Variant(&'tcx ty::VariantDef),
177 Field(&'tcx ty::FieldDef),
178 Primitive,
179 }
180
181 impl<'tcx> super::Def for Def<'tcx> {
182 fn has_safety_invariants(&self) -> bool {
183 self != &Self::Primitive
187 }
188 }
189
190 pub(crate) fn layout_of<'tcx>(
191 cx: LayoutCx<'tcx>,
192 ty: Ty<'tcx>,
193 ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
194 use rustc_middle::ty::layout::LayoutOf;
195 let ty = cx.tcx().erase_regions(ty);
196 cx.layout_of(ty).map(|tl| tl.layout)
197 }
198}