| //! Common utilities shared by both `rustc_ast` and `rustc_type_ir`. |
| //! |
| //! Don't depend on this crate directly; both of those crates should re-export |
| //! the functionality. Additionally, if you're in scope of `rustc_middle`, then |
| //! prefer imports via that too, to avoid needing to directly depend on (e.g.) |
| //! `rustc_type_ir` for a single import. |
| |
| // tidy-alphabetical-start |
| #![cfg_attr(feature = "nightly", allow(internal_features))] |
| #![cfg_attr(feature = "nightly", feature(never_type))] |
| #![cfg_attr(feature = "nightly", feature(rustc_attrs))] |
| // tidy-alphabetical-end |
| |
| use std::fmt; |
| |
| #[cfg(feature = "nightly")] |
| use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; |
| #[cfg(feature = "nightly")] |
| use rustc_span::{Symbol, sym}; |
| |
| pub mod visit; |
| |
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum IntTy { |
| Isize, |
| I8, |
| I16, |
| I32, |
| I64, |
| I128, |
| } |
| |
| impl IntTy { |
| pub fn name_str(&self) -> &'static str { |
| match *self { |
| IntTy::Isize => "isize", |
| IntTy::I8 => "i8", |
| IntTy::I16 => "i16", |
| IntTy::I32 => "i32", |
| IntTy::I64 => "i64", |
| IntTy::I128 => "i128", |
| } |
| } |
| |
| #[cfg(feature = "nightly")] |
| pub fn name(self) -> Symbol { |
| match self { |
| IntTy::Isize => sym::isize, |
| IntTy::I8 => sym::i8, |
| IntTy::I16 => sym::i16, |
| IntTy::I32 => sym::i32, |
| IntTy::I64 => sym::i64, |
| IntTy::I128 => sym::i128, |
| } |
| } |
| |
| pub fn bit_width(&self) -> Option<u64> { |
| Some(match *self { |
| IntTy::Isize => return None, |
| IntTy::I8 => 8, |
| IntTy::I16 => 16, |
| IntTy::I32 => 32, |
| IntTy::I64 => 64, |
| IntTy::I128 => 128, |
| }) |
| } |
| |
| pub fn normalize(&self, target_width: u32) -> Self { |
| match self { |
| IntTy::Isize => match target_width { |
| 16 => IntTy::I16, |
| 32 => IntTy::I32, |
| 64 => IntTy::I64, |
| _ => unreachable!(), |
| }, |
| _ => *self, |
| } |
| } |
| |
| pub fn to_unsigned(self) -> UintTy { |
| match self { |
| IntTy::Isize => UintTy::Usize, |
| IntTy::I8 => UintTy::U8, |
| IntTy::I16 => UintTy::U16, |
| IntTy::I32 => UintTy::U32, |
| IntTy::I64 => UintTy::U64, |
| IntTy::I128 => UintTy::U128, |
| } |
| } |
| } |
| |
| impl fmt::Debug for IntTy { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", self.name_str()) |
| } |
| } |
| |
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum UintTy { |
| Usize, |
| U8, |
| U16, |
| U32, |
| U64, |
| U128, |
| } |
| |
| impl UintTy { |
| pub fn name_str(&self) -> &'static str { |
| match *self { |
| UintTy::Usize => "usize", |
| UintTy::U8 => "u8", |
| UintTy::U16 => "u16", |
| UintTy::U32 => "u32", |
| UintTy::U64 => "u64", |
| UintTy::U128 => "u128", |
| } |
| } |
| |
| #[cfg(feature = "nightly")] |
| pub fn name(self) -> Symbol { |
| match self { |
| UintTy::Usize => sym::usize, |
| UintTy::U8 => sym::u8, |
| UintTy::U16 => sym::u16, |
| UintTy::U32 => sym::u32, |
| UintTy::U64 => sym::u64, |
| UintTy::U128 => sym::u128, |
| } |
| } |
| |
| pub fn bit_width(&self) -> Option<u64> { |
| Some(match *self { |
| UintTy::Usize => return None, |
| UintTy::U8 => 8, |
| UintTy::U16 => 16, |
| UintTy::U32 => 32, |
| UintTy::U64 => 64, |
| UintTy::U128 => 128, |
| }) |
| } |
| |
| pub fn normalize(&self, target_width: u32) -> Self { |
| match self { |
| UintTy::Usize => match target_width { |
| 16 => UintTy::U16, |
| 32 => UintTy::U32, |
| 64 => UintTy::U64, |
| _ => unreachable!(), |
| }, |
| _ => *self, |
| } |
| } |
| |
| pub fn to_signed(self) -> IntTy { |
| match self { |
| UintTy::Usize => IntTy::Isize, |
| UintTy::U8 => IntTy::I8, |
| UintTy::U16 => IntTy::I16, |
| UintTy::U32 => IntTy::I32, |
| UintTy::U64 => IntTy::I64, |
| UintTy::U128 => IntTy::I128, |
| } |
| } |
| } |
| |
| impl fmt::Debug for UintTy { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", self.name_str()) |
| } |
| } |
| |
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum FloatTy { |
| F16, |
| F32, |
| F64, |
| F128, |
| } |
| |
| impl FloatTy { |
| pub fn name_str(self) -> &'static str { |
| match self { |
| FloatTy::F16 => "f16", |
| FloatTy::F32 => "f32", |
| FloatTy::F64 => "f64", |
| FloatTy::F128 => "f128", |
| } |
| } |
| |
| #[cfg(feature = "nightly")] |
| pub fn name(self) -> Symbol { |
| match self { |
| FloatTy::F16 => sym::f16, |
| FloatTy::F32 => sym::f32, |
| FloatTy::F64 => sym::f64, |
| FloatTy::F128 => sym::f128, |
| } |
| } |
| |
| pub fn bit_width(self) -> u64 { |
| match self { |
| FloatTy::F16 => 16, |
| FloatTy::F32 => 32, |
| FloatTy::F64 => 64, |
| FloatTy::F128 => 128, |
| } |
| } |
| } |
| |
| impl fmt::Debug for FloatTy { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", self.name_str()) |
| } |
| } |
| |
| /// The movability of a coroutine / closure literal: |
| /// whether a coroutine contains self-references, causing it to be `!Unpin`. |
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum Movability { |
| /// May contain self-references, `!Unpin`. |
| Static, |
| /// Must not contain self-references, `Unpin`. |
| Movable, |
| } |
| |
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum Mutability { |
| // N.B. Order is deliberate, so that Not < Mut |
| Not, |
| Mut, |
| } |
| |
| impl Mutability { |
| pub fn invert(self) -> Self { |
| match self { |
| Mutability::Mut => Mutability::Not, |
| Mutability::Not => Mutability::Mut, |
| } |
| } |
| |
| /// Returns `""` (empty string) or `"mut "` depending on the mutability. |
| pub fn prefix_str(self) -> &'static str { |
| match self { |
| Mutability::Mut => "mut ", |
| Mutability::Not => "", |
| } |
| } |
| |
| /// Returns `"&"` or `"&mut "` depending on the mutability. |
| pub fn ref_prefix_str(self) -> &'static str { |
| match self { |
| Mutability::Not => "&", |
| Mutability::Mut => "&mut ", |
| } |
| } |
| |
| /// Returns `"const"` or `"mut"` depending on the mutability. |
| pub fn ptr_str(self) -> &'static str { |
| match self { |
| Mutability::Not => "const", |
| Mutability::Mut => "mut", |
| } |
| } |
| |
| /// Returns `""` (empty string) or `"mutably "` depending on the mutability. |
| pub fn mutably_str(self) -> &'static str { |
| match self { |
| Mutability::Not => "", |
| Mutability::Mut => "mutably ", |
| } |
| } |
| |
| /// Return `true` if self is mutable |
| pub fn is_mut(self) -> bool { |
| matches!(self, Self::Mut) |
| } |
| |
| /// Return `true` if self is **not** mutable |
| pub fn is_not(self) -> bool { |
| matches!(self, Self::Not) |
| } |
| } |
| |
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] |
| #[cfg_attr( |
| feature = "nightly", |
| derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) |
| )] |
| pub enum Pinnedness { |
| Not, |
| Pinned, |
| } |