rustc_ast_ir/
lib.rs

1//! Common utilities shared by both `rustc_ast` and `rustc_type_ir`.
2//!
3//! Don't depend on this crate directly; both of those crates should re-export
4//! the functionality. Additionally, if you're in scope of `rustc_middle`, then
5//! prefer imports via that too, to avoid needing to directly depend on (e.g.)
6//! `rustc_type_ir` for a single import.
7
8// tidy-alphabetical-start
9#![cfg_attr(feature = "nightly", allow(internal_features))]
10#![cfg_attr(feature = "nightly", feature(never_type))]
11#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
12// tidy-alphabetical-end
13
14use std::fmt;
15
16#[cfg(feature = "nightly")]
17use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
18#[cfg(feature = "nightly")]
19use rustc_span::{Symbol, sym};
20
21pub mod visit;
22
23#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[cfg_attr(
25    feature = "nightly",
26    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
27)]
28pub enum IntTy {
29    Isize,
30    I8,
31    I16,
32    I32,
33    I64,
34    I128,
35}
36
37impl IntTy {
38    pub fn name_str(&self) -> &'static str {
39        match *self {
40            IntTy::Isize => "isize",
41            IntTy::I8 => "i8",
42            IntTy::I16 => "i16",
43            IntTy::I32 => "i32",
44            IntTy::I64 => "i64",
45            IntTy::I128 => "i128",
46        }
47    }
48
49    #[cfg(feature = "nightly")]
50    pub fn name(self) -> Symbol {
51        match self {
52            IntTy::Isize => sym::isize,
53            IntTy::I8 => sym::i8,
54            IntTy::I16 => sym::i16,
55            IntTy::I32 => sym::i32,
56            IntTy::I64 => sym::i64,
57            IntTy::I128 => sym::i128,
58        }
59    }
60
61    pub fn bit_width(&self) -> Option<u64> {
62        Some(match *self {
63            IntTy::Isize => return None,
64            IntTy::I8 => 8,
65            IntTy::I16 => 16,
66            IntTy::I32 => 32,
67            IntTy::I64 => 64,
68            IntTy::I128 => 128,
69        })
70    }
71
72    pub fn normalize(&self, target_width: u32) -> Self {
73        match self {
74            IntTy::Isize => match target_width {
75                16 => IntTy::I16,
76                32 => IntTy::I32,
77                64 => IntTy::I64,
78                _ => unreachable!(),
79            },
80            _ => *self,
81        }
82    }
83
84    pub fn to_unsigned(self) -> UintTy {
85        match self {
86            IntTy::Isize => UintTy::Usize,
87            IntTy::I8 => UintTy::U8,
88            IntTy::I16 => UintTy::U16,
89            IntTy::I32 => UintTy::U32,
90            IntTy::I64 => UintTy::U64,
91            IntTy::I128 => UintTy::U128,
92        }
93    }
94}
95
96impl fmt::Debug for IntTy {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(f, "{}", self.name_str())
99    }
100}
101
102#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
103#[cfg_attr(
104    feature = "nightly",
105    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
106)]
107pub enum UintTy {
108    Usize,
109    U8,
110    U16,
111    U32,
112    U64,
113    U128,
114}
115
116impl UintTy {
117    pub fn name_str(&self) -> &'static str {
118        match *self {
119            UintTy::Usize => "usize",
120            UintTy::U8 => "u8",
121            UintTy::U16 => "u16",
122            UintTy::U32 => "u32",
123            UintTy::U64 => "u64",
124            UintTy::U128 => "u128",
125        }
126    }
127
128    #[cfg(feature = "nightly")]
129    pub fn name(self) -> Symbol {
130        match self {
131            UintTy::Usize => sym::usize,
132            UintTy::U8 => sym::u8,
133            UintTy::U16 => sym::u16,
134            UintTy::U32 => sym::u32,
135            UintTy::U64 => sym::u64,
136            UintTy::U128 => sym::u128,
137        }
138    }
139
140    pub fn bit_width(&self) -> Option<u64> {
141        Some(match *self {
142            UintTy::Usize => return None,
143            UintTy::U8 => 8,
144            UintTy::U16 => 16,
145            UintTy::U32 => 32,
146            UintTy::U64 => 64,
147            UintTy::U128 => 128,
148        })
149    }
150
151    pub fn normalize(&self, target_width: u32) -> Self {
152        match self {
153            UintTy::Usize => match target_width {
154                16 => UintTy::U16,
155                32 => UintTy::U32,
156                64 => UintTy::U64,
157                _ => unreachable!(),
158            },
159            _ => *self,
160        }
161    }
162
163    pub fn to_signed(self) -> IntTy {
164        match self {
165            UintTy::Usize => IntTy::Isize,
166            UintTy::U8 => IntTy::I8,
167            UintTy::U16 => IntTy::I16,
168            UintTy::U32 => IntTy::I32,
169            UintTy::U64 => IntTy::I64,
170            UintTy::U128 => IntTy::I128,
171        }
172    }
173}
174
175impl fmt::Debug for UintTy {
176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177        write!(f, "{}", self.name_str())
178    }
179}
180
181#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
182#[cfg_attr(
183    feature = "nightly",
184    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
185)]
186pub enum FloatTy {
187    F16,
188    F32,
189    F64,
190    F128,
191}
192
193impl FloatTy {
194    pub fn name_str(self) -> &'static str {
195        match self {
196            FloatTy::F16 => "f16",
197            FloatTy::F32 => "f32",
198            FloatTy::F64 => "f64",
199            FloatTy::F128 => "f128",
200        }
201    }
202
203    #[cfg(feature = "nightly")]
204    pub fn name(self) -> Symbol {
205        match self {
206            FloatTy::F16 => sym::f16,
207            FloatTy::F32 => sym::f32,
208            FloatTy::F64 => sym::f64,
209            FloatTy::F128 => sym::f128,
210        }
211    }
212
213    pub fn bit_width(self) -> u64 {
214        match self {
215            FloatTy::F16 => 16,
216            FloatTy::F32 => 32,
217            FloatTy::F64 => 64,
218            FloatTy::F128 => 128,
219        }
220    }
221}
222
223impl fmt::Debug for FloatTy {
224    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225        write!(f, "{}", self.name_str())
226    }
227}
228
229/// The movability of a coroutine / closure literal:
230/// whether a coroutine contains self-references, causing it to be `!Unpin`.
231#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
232#[cfg_attr(
233    feature = "nightly",
234    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
235)]
236pub enum Movability {
237    /// May contain self-references, `!Unpin`.
238    Static,
239    /// Must not contain self-references, `Unpin`.
240    Movable,
241}
242
243#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
244#[cfg_attr(
245    feature = "nightly",
246    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
247)]
248pub enum Mutability {
249    // N.B. Order is deliberate, so that Not < Mut
250    Not,
251    Mut,
252}
253
254impl Mutability {
255    pub fn invert(self) -> Self {
256        match self {
257            Mutability::Mut => Mutability::Not,
258            Mutability::Not => Mutability::Mut,
259        }
260    }
261
262    /// Returns `""` (empty string) or `"mut "` depending on the mutability.
263    pub fn prefix_str(self) -> &'static str {
264        match self {
265            Mutability::Mut => "mut ",
266            Mutability::Not => "",
267        }
268    }
269
270    /// Returns `"&"` or `"&mut "` depending on the mutability.
271    pub fn ref_prefix_str(self) -> &'static str {
272        match self {
273            Mutability::Not => "&",
274            Mutability::Mut => "&mut ",
275        }
276    }
277
278    /// Returns `"const"` or `"mut"` depending on the mutability.
279    pub fn ptr_str(self) -> &'static str {
280        match self {
281            Mutability::Not => "const",
282            Mutability::Mut => "mut",
283        }
284    }
285
286    /// Returns `""` (empty string) or `"mutably "` depending on the mutability.
287    pub fn mutably_str(self) -> &'static str {
288        match self {
289            Mutability::Not => "",
290            Mutability::Mut => "mutably ",
291        }
292    }
293
294    /// Return `true` if self is mutable
295    pub fn is_mut(self) -> bool {
296        matches!(self, Self::Mut)
297    }
298
299    /// Return `true` if self is **not** mutable
300    pub fn is_not(self) -> bool {
301        matches!(self, Self::Not)
302    }
303}
304
305#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
306#[cfg_attr(
307    feature = "nightly",
308    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
309)]
310pub enum Pinnedness {
311    Not,
312    Pinned,
313}