| //! 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: u16) -> 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: u16) -> 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, | |
| } | |
| impl Pinnedness { | |
| /// Return `true` if self is pinned | |
| pub fn is_pinned(self) -> bool { | |
| matches!(self, Self::Pinned) | |
| } | |
| /// Returns `""` (empty string), "mut", `"pin mut "` or `"pin const "` depending | |
| /// on the pinnedness and mutability. | |
| pub fn prefix_str(self, mutbl: Mutability) -> &'static str { | |
| match (self, mutbl) { | |
| (Pinnedness::Pinned, Mutability::Mut) => "pin mut ", | |
| (Pinnedness::Pinned, Mutability::Not) => "pin const ", | |
| (Pinnedness::Not, Mutability::Mut) => "mut ", | |
| (Pinnedness::Not, Mutability::Not) => "", | |
| } | |
| } | |
| } |