|  | use std::fmt::{self, Debug, Display, Formatter}; | 
|  | use std::ops::Range; | 
|  |  | 
|  | use serde::Serialize; | 
|  |  | 
|  | use super::abi::ReprOptions; | 
|  | use super::mir::{Body, Mutability, Safety}; | 
|  | use super::{DefId, Error, Symbol, with}; | 
|  | use crate::abi::{FnAbi, Layout}; | 
|  | use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; | 
|  | use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; | 
|  | use crate::mir::mono::StaticDef; | 
|  | use crate::target::MachineInfo; | 
|  | use crate::{Filename, IndexedVal, Opaque}; | 
|  |  | 
|  | #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] | 
|  | pub struct Ty(usize); | 
|  |  | 
|  | impl Debug for Ty { | 
|  | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 
|  | f.debug_struct("Ty").field("id", &self.0).field("kind", &self.kind()).finish() | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Constructors for `Ty`. | 
|  | impl Ty { | 
|  | /// Create a new type from a given kind. | 
|  | pub fn from_rigid_kind(kind: RigidTy) -> Ty { | 
|  | with(|cx| cx.new_rigid_ty(kind)) | 
|  | } | 
|  |  | 
|  | /// Create a new array type. | 
|  | pub fn try_new_array(elem_ty: Ty, size: u64) -> Result<Ty, Error> { | 
|  | Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?))) | 
|  | } | 
|  |  | 
|  | /// Create a new array type from Const length. | 
|  | pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) | 
|  | } | 
|  |  | 
|  | /// Create a new pointer type. | 
|  | pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability)) | 
|  | } | 
|  |  | 
|  | /// Create a new reference type. | 
|  | pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability)) | 
|  | } | 
|  |  | 
|  | /// Create a new pointer type. | 
|  | pub fn new_tuple(tys: &[Ty]) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys))) | 
|  | } | 
|  |  | 
|  | /// Create a new closure type. | 
|  | pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Closure(def, args)) | 
|  | } | 
|  |  | 
|  | /// Create a new coroutine type. | 
|  | pub fn new_coroutine(def: CoroutineDef, args: GenericArgs) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Coroutine(def, args)) | 
|  | } | 
|  |  | 
|  | /// Create a new closure type. | 
|  | pub fn new_coroutine_closure(def: CoroutineClosureDef, args: GenericArgs) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::CoroutineClosure(def, args)) | 
|  | } | 
|  |  | 
|  | /// Create a new box type that represents `Box<T>`, for the given inner type `T`. | 
|  | pub fn new_box(inner_ty: Ty) -> Ty { | 
|  | with(|cx| cx.new_box_ty(inner_ty)) | 
|  | } | 
|  |  | 
|  | /// Create a type representing `usize`. | 
|  | pub fn usize_ty() -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize)) | 
|  | } | 
|  |  | 
|  | /// Create a type representing `bool`. | 
|  | pub fn bool_ty() -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Bool) | 
|  | } | 
|  |  | 
|  | /// Create a type representing a signed integer. | 
|  | pub fn signed_ty(inner: IntTy) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Int(inner)) | 
|  | } | 
|  |  | 
|  | /// Create a type representing an unsigned integer. | 
|  | pub fn unsigned_ty(inner: UintTy) -> Ty { | 
|  | Ty::from_rigid_kind(RigidTy::Uint(inner)) | 
|  | } | 
|  |  | 
|  | /// Get a type layout. | 
|  | pub fn layout(self) -> Result<Layout, Error> { | 
|  | with(|cx| cx.ty_layout(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Ty { | 
|  | pub fn kind(&self) -> TyKind { | 
|  | with(|context| context.ty_kind(*self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Represents a pattern in the type system | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum Pattern { | 
|  | Range { start: Option<TyConst>, end: Option<TyConst>, include_end: bool }, | 
|  | } | 
|  |  | 
|  | /// Represents a constant in the type system | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct TyConst { | 
|  | pub(crate) kind: TyConstKind, | 
|  | pub id: TyConstId, | 
|  | } | 
|  |  | 
|  | impl TyConst { | 
|  | pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst { | 
|  | Self { kind, id } | 
|  | } | 
|  |  | 
|  | /// Retrieve the constant kind. | 
|  | pub fn kind(&self) -> &TyConstKind { | 
|  | &self.kind | 
|  | } | 
|  |  | 
|  | /// Creates an interned usize constant. | 
|  | pub fn try_from_target_usize(val: u64) -> Result<Self, Error> { | 
|  | with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) | 
|  | } | 
|  |  | 
|  | /// Try to evaluate to a target `usize`. | 
|  | pub fn eval_target_usize(&self) -> Result<u64, Error> { | 
|  | with(|cx| cx.eval_target_usize_ty(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum TyConstKind { | 
|  | Param(ParamConst), | 
|  | Bound(DebruijnIndex, BoundVar), | 
|  | Unevaluated(ConstDef, GenericArgs), | 
|  |  | 
|  | // FIXME: These should be a valtree | 
|  | Value(Ty, Allocation), | 
|  | ZSTValue(Ty), | 
|  | } | 
|  |  | 
|  | #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct TyConstId(usize); | 
|  |  | 
|  | /// Represents a constant in MIR | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct MirConst { | 
|  | /// The constant kind. | 
|  | pub(crate) kind: ConstantKind, | 
|  | /// The constant type. | 
|  | pub(crate) ty: Ty, | 
|  | /// Used for internal tracking of the internal constant. | 
|  | pub id: MirConstId, | 
|  | } | 
|  |  | 
|  | impl MirConst { | 
|  | /// Build a constant. Note that this should only be used by the compiler. | 
|  | pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst { | 
|  | MirConst { kind, ty, id } | 
|  | } | 
|  |  | 
|  | /// Retrieve the constant kind. | 
|  | pub fn kind(&self) -> &ConstantKind { | 
|  | &self.kind | 
|  | } | 
|  |  | 
|  | /// Get the constant type. | 
|  | pub fn ty(&self) -> Ty { | 
|  | self.ty | 
|  | } | 
|  |  | 
|  | /// Try to evaluate to a target `usize`. | 
|  | pub fn eval_target_usize(&self) -> Result<u64, Error> { | 
|  | with(|cx| cx.eval_target_usize(self)) | 
|  | } | 
|  |  | 
|  | /// Create a constant that represents a new zero-sized constant of type T. | 
|  | /// Fails if the type is not a ZST or if it doesn't have a known size. | 
|  | pub fn try_new_zero_sized(ty: Ty) -> Result<MirConst, Error> { | 
|  | with(|cx| cx.try_new_const_zst(ty)) | 
|  | } | 
|  |  | 
|  | /// Build a new constant that represents the given string. | 
|  | /// | 
|  | /// Note that there is no guarantee today about duplication of the same constant. | 
|  | /// I.e.: Calling this function multiple times with the same argument may or may not return | 
|  | /// the same allocation. | 
|  | pub fn from_str(value: &str) -> MirConst { | 
|  | with(|cx| cx.new_const_str(value)) | 
|  | } | 
|  |  | 
|  | /// Build a new constant that represents the given boolean value. | 
|  | pub fn from_bool(value: bool) -> MirConst { | 
|  | with(|cx| cx.new_const_bool(value)) | 
|  | } | 
|  |  | 
|  | /// Build a new constant that represents the given unsigned integer. | 
|  | pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { | 
|  | with(|cx| cx.try_new_const_uint(value, uint_ty)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub struct MirConstId(usize); | 
|  |  | 
|  | type Ident = Opaque; | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct Region { | 
|  | pub kind: RegionKind, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum RegionKind { | 
|  | ReEarlyParam(EarlyParamRegion), | 
|  | ReBound(DebruijnIndex, BoundRegion), | 
|  | ReStatic, | 
|  | RePlaceholder(Placeholder<BoundRegion>), | 
|  | ReErased, | 
|  | } | 
|  |  | 
|  | pub(crate) type DebruijnIndex = u32; | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct EarlyParamRegion { | 
|  | pub index: u32, | 
|  | pub name: Symbol, | 
|  | } | 
|  |  | 
|  | pub(crate) type BoundVar = u32; | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct BoundRegion { | 
|  | pub var: BoundVar, | 
|  | pub kind: BoundRegionKind, | 
|  | } | 
|  |  | 
|  | pub(crate) type UniverseIndex = u32; | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct Placeholder<T> { | 
|  | pub universe: UniverseIndex, | 
|  | pub bound: T, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, PartialEq, Eq, Serialize)] | 
|  | pub struct Span(usize); | 
|  |  | 
|  | impl Debug for Span { | 
|  | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 
|  | f.debug_struct("Span") | 
|  | .field("id", &self.0) | 
|  | .field("repr", &with(|cx| cx.span_to_string(*self))) | 
|  | .finish() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Span { | 
|  | /// Return filename for diagnostic purposes | 
|  | pub fn get_filename(&self) -> Filename { | 
|  | with(|c| c.get_filename(self)) | 
|  | } | 
|  |  | 
|  | /// Return lines that correspond to this `Span` | 
|  | pub fn get_lines(&self) -> LineInfo { | 
|  | with(|c| c.get_lines(self)) | 
|  | } | 
|  |  | 
|  | /// Return the span location to be printed in diagnostic messages. | 
|  | /// | 
|  | /// This may leak local file paths and should not be used to build artifacts that may be | 
|  | /// distributed. | 
|  | pub fn diagnostic(&self) -> String { | 
|  | with(|c| c.span_to_string(*self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, Serialize)] | 
|  | /// Information you get from `Span` in a struct form. | 
|  | /// Line and col start from 1. | 
|  | pub struct LineInfo { | 
|  | pub start_line: usize, | 
|  | pub start_col: usize, | 
|  | pub end_line: usize, | 
|  | pub end_col: usize, | 
|  | } | 
|  |  | 
|  | impl LineInfo { | 
|  | pub fn from(lines: (usize, usize, usize, usize)) -> Self { | 
|  | LineInfo { start_line: lines.0, start_col: lines.1, end_line: lines.2, end_col: lines.3 } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum TyKind { | 
|  | RigidTy(RigidTy), | 
|  | Alias(AliasKind, AliasTy), | 
|  | Param(ParamTy), | 
|  | Bound(usize, BoundTy), | 
|  | } | 
|  |  | 
|  | impl TyKind { | 
|  | pub fn rigid(&self) -> Option<&RigidTy> { | 
|  | if let TyKind::RigidTy(inner) = self { Some(inner) } else { None } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_unit(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Tuple(data)) if data.is_empty()) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_bool(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Bool)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_char(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Char)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_trait(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_enum(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Enum) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_struct(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Struct) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_union(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Union) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_adt(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Adt(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_ref(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Ref(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_fn(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::FnDef(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_fn_ptr(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::FnPtr(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_primitive(&self) -> bool { | 
|  | matches!( | 
|  | self, | 
|  | TyKind::RigidTy( | 
|  | RigidTy::Bool | 
|  | | RigidTy::Char | 
|  | | RigidTy::Int(_) | 
|  | | RigidTy::Uint(_) | 
|  | | RigidTy::Float(_) | 
|  | ) | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_float(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Float(_))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_integral(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Int(_) | RigidTy::Uint(_))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_numeric(&self) -> bool { | 
|  | self.is_integral() || self.is_float() | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_signed(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Int(_))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_str(&self) -> bool { | 
|  | *self == TyKind::RigidTy(RigidTy::Str) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_cstr(&self) -> bool { | 
|  | let TyKind::RigidTy(RigidTy::Adt(def, _)) = self else { | 
|  | return false; | 
|  | }; | 
|  | with(|cx| cx.adt_is_cstr(*def)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_slice(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Slice(_))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_array(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Array(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_mutable_ptr(&self) -> bool { | 
|  | matches!( | 
|  | self, | 
|  | TyKind::RigidTy(RigidTy::RawPtr(_, Mutability::Mut)) | 
|  | | TyKind::RigidTy(RigidTy::Ref(_, _, Mutability::Mut)) | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_raw_ptr(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::RawPtr(..))) | 
|  | } | 
|  |  | 
|  | /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). | 
|  | #[inline] | 
|  | pub fn is_any_ptr(&self) -> bool { | 
|  | self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr() | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_coroutine(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Coroutine(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_closure(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Closure(..))) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_box(&self) -> bool { | 
|  | match self { | 
|  | TyKind::RigidTy(RigidTy::Adt(def, _)) => def.is_box(), | 
|  | _ => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub fn is_simd(&self) -> bool { | 
|  | matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.is_simd()) | 
|  | } | 
|  |  | 
|  | pub fn trait_principal(&self) -> Option<Binder<ExistentialTraitRef>> { | 
|  | if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self { | 
|  | if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) = | 
|  | predicates.first() | 
|  | { | 
|  | Some(Binder { value: trait_ref.clone(), bound_vars: bound_vars.clone() }) | 
|  | } else { | 
|  | None | 
|  | } | 
|  | } else { | 
|  | None | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Returns the type of `ty[i]` for builtin types. | 
|  | pub fn builtin_index(&self) -> Option<Ty> { | 
|  | match self.rigid()? { | 
|  | RigidTy::Array(ty, _) | RigidTy::Slice(ty) => Some(*ty), | 
|  | _ => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Returns the type and mutability of `*ty` for builtin types. | 
|  | /// | 
|  | /// The parameter `explicit` indicates if this is an *explicit* dereference. | 
|  | /// Some types -- notably raw ptrs -- can only be dereferenced explicitly. | 
|  | pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut> { | 
|  | match self.rigid()? { | 
|  | RigidTy::Adt(def, args) if def.is_box() => { | 
|  | Some(TypeAndMut { ty: *args.0.first()?.ty()?, mutability: Mutability::Not }) | 
|  | } | 
|  | RigidTy::Ref(_, ty, mutability) => { | 
|  | Some(TypeAndMut { ty: *ty, mutability: *mutability }) | 
|  | } | 
|  | RigidTy::RawPtr(ty, mutability) if explicit => { | 
|  | Some(TypeAndMut { ty: *ty, mutability: *mutability }) | 
|  | } | 
|  | _ => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Get the function signature for function like types (Fn, FnPtr, and Closure) | 
|  | pub fn fn_sig(&self) -> Option<PolyFnSig> { | 
|  | match self { | 
|  | TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))), | 
|  | TyKind::RigidTy(RigidTy::FnPtr(sig)) => Some(sig.clone()), | 
|  | TyKind::RigidTy(RigidTy::Closure(_def, args)) => Some(with(|cx| cx.closure_sig(args))), | 
|  | _ => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Get the discriminant type for this type. | 
|  | pub fn discriminant_ty(&self) -> Option<Ty> { | 
|  | self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty))) | 
|  | } | 
|  |  | 
|  | /// Deconstruct a function type if this is one. | 
|  | pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> { | 
|  | if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self { | 
|  | Some((*def, args)) | 
|  | } else { | 
|  | None | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub struct TypeAndMut { | 
|  | pub ty: Ty, | 
|  | pub mutability: Mutability, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum RigidTy { | 
|  | Bool, | 
|  | Char, | 
|  | Int(IntTy), | 
|  | Uint(UintTy), | 
|  | Float(FloatTy), | 
|  | Adt(AdtDef, GenericArgs), | 
|  | Foreign(ForeignDef), | 
|  | Str, | 
|  | Array(Ty, TyConst), | 
|  | Pat(Ty, Pattern), | 
|  | Slice(Ty), | 
|  | RawPtr(Ty, Mutability), | 
|  | Ref(Region, Ty, Mutability), | 
|  | FnDef(FnDef, GenericArgs), | 
|  | FnPtr(PolyFnSig), | 
|  | Closure(ClosureDef, GenericArgs), | 
|  | Coroutine(CoroutineDef, GenericArgs), | 
|  | CoroutineClosure(CoroutineClosureDef, GenericArgs), | 
|  | Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind), | 
|  | Never, | 
|  | Tuple(Vec<Ty>), | 
|  | CoroutineWitness(CoroutineWitnessDef, GenericArgs), | 
|  | } | 
|  |  | 
|  | impl RigidTy { | 
|  | /// Get the discriminant type for this type. | 
|  | pub fn discriminant_ty(&self) -> Ty { | 
|  | with(|cx| cx.rigid_ty_discriminant_ty(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<RigidTy> for TyKind { | 
|  | fn from(value: RigidTy) -> Self { | 
|  | TyKind::RigidTy(value) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub enum IntTy { | 
|  | Isize, | 
|  | I8, | 
|  | I16, | 
|  | I32, | 
|  | I64, | 
|  | I128, | 
|  | } | 
|  |  | 
|  | impl IntTy { | 
|  | pub fn num_bytes(self) -> usize { | 
|  | match self { | 
|  | IntTy::Isize => MachineInfo::target_pointer_width().bytes(), | 
|  | IntTy::I8 => 1, | 
|  | IntTy::I16 => 2, | 
|  | IntTy::I32 => 4, | 
|  | IntTy::I64 => 8, | 
|  | IntTy::I128 => 16, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub enum UintTy { | 
|  | Usize, | 
|  | U8, | 
|  | U16, | 
|  | U32, | 
|  | U64, | 
|  | U128, | 
|  | } | 
|  |  | 
|  | impl UintTy { | 
|  | pub fn num_bytes(self) -> usize { | 
|  | match self { | 
|  | UintTy::Usize => MachineInfo::target_pointer_width().bytes(), | 
|  | UintTy::U8 => 1, | 
|  | UintTy::U16 => 2, | 
|  | UintTy::U32 => 4, | 
|  | UintTy::U64 => 8, | 
|  | UintTy::U128 => 16, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub enum FloatTy { | 
|  | F16, | 
|  | F32, | 
|  | F64, | 
|  | F128, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub enum Movability { | 
|  | Static, | 
|  | Movable, | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub ForeignModuleDef; | 
|  | } | 
|  |  | 
|  | impl ForeignModuleDef { | 
|  | pub fn module(&self) -> ForeignModule { | 
|  | with(|cx| cx.foreign_module(*self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub struct ForeignModule { | 
|  | pub def_id: ForeignModuleDef, | 
|  | pub abi: Abi, | 
|  | } | 
|  |  | 
|  | impl ForeignModule { | 
|  | pub fn items(&self) -> Vec<ForeignDef> { | 
|  | with(|cx| cx.foreign_items(self.def_id)) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def_with_ty! { | 
|  | /// Hold information about a ForeignItem in a crate. | 
|  | #[derive(Serialize)] | 
|  | pub ForeignDef; | 
|  | } | 
|  |  | 
|  | impl ForeignDef { | 
|  | pub fn kind(&self) -> ForeignItemKind { | 
|  | with(|cx| cx.foreign_item_kind(*self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] | 
|  | pub enum ForeignItemKind { | 
|  | Fn(FnDef), | 
|  | Static(StaticDef), | 
|  | Type(Ty), | 
|  | } | 
|  |  | 
|  | crate_def_with_ty! { | 
|  | /// Hold information about a function definition in a crate. | 
|  | #[derive(Serialize)] | 
|  | pub FnDef; | 
|  | } | 
|  |  | 
|  | impl FnDef { | 
|  | // Get the function body if available. | 
|  | pub fn body(&self) -> Option<Body> { | 
|  | with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) | 
|  | } | 
|  |  | 
|  | // Check if the function body is available. | 
|  | pub fn has_body(&self) -> bool { | 
|  | with(|ctx| ctx.has_body(self.0)) | 
|  | } | 
|  |  | 
|  | /// Get the information of the intrinsic if this function is a definition of one. | 
|  | pub fn as_intrinsic(&self) -> Option<IntrinsicDef> { | 
|  | with(|cx| cx.intrinsic(self.def_id())) | 
|  | } | 
|  |  | 
|  | /// Check if the function is an intrinsic. | 
|  | #[inline] | 
|  | pub fn is_intrinsic(&self) -> bool { | 
|  | self.as_intrinsic().is_some() | 
|  | } | 
|  |  | 
|  | /// Get the function signature for this function definition. | 
|  | pub fn fn_sig(&self) -> PolyFnSig { | 
|  | let kind = self.ty().kind(); | 
|  | kind.fn_sig().unwrap() | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def_with_ty! { | 
|  | #[derive(Serialize)] | 
|  | pub IntrinsicDef; | 
|  | } | 
|  |  | 
|  | impl IntrinsicDef { | 
|  | /// Returns the plain name of the intrinsic. | 
|  | /// e.g., `transmute` for `core::intrinsics::transmute`. | 
|  | pub fn fn_name(&self) -> Symbol { | 
|  | with(|cx| cx.intrinsic_name(*self)) | 
|  | } | 
|  |  | 
|  | /// Returns whether the intrinsic has no meaningful body and all backends | 
|  | /// need to shim all calls to it. | 
|  | pub fn must_be_overridden(&self) -> bool { | 
|  | with(|cx| !cx.has_body(self.0)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<IntrinsicDef> for FnDef { | 
|  | fn from(def: IntrinsicDef) -> Self { | 
|  | FnDef(def.0) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub ClosureDef; | 
|  | } | 
|  |  | 
|  | impl ClosureDef { | 
|  | /// Retrieves the body of the closure definition. Returns None if the body | 
|  | /// isn't available. | 
|  | pub fn body(&self) -> Option<Body> { | 
|  | with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub CoroutineDef; | 
|  | } | 
|  |  | 
|  | impl CoroutineDef { | 
|  | /// Retrieves the body of the coroutine definition. Returns None if the body | 
|  | /// isn't available. | 
|  | pub fn body(&self) -> Option<Body> { | 
|  | with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) | 
|  | } | 
|  |  | 
|  | pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr { | 
|  | with(|cx| cx.coroutine_discr_for_variant(*self, args, idx)) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub CoroutineClosureDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub ParamDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub BrNamedDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub AdtDef; | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] | 
|  | pub enum AdtKind { | 
|  | Enum, | 
|  | Union, | 
|  | Struct, | 
|  | } | 
|  |  | 
|  | impl AdtDef { | 
|  | pub fn kind(&self) -> AdtKind { | 
|  | with(|cx| cx.adt_kind(*self)) | 
|  | } | 
|  |  | 
|  | /// Retrieve the type of this Adt. | 
|  | pub fn ty(&self) -> Ty { | 
|  | with(|cx| cx.def_ty(self.0)) | 
|  | } | 
|  |  | 
|  | /// Retrieve the type of this Adt by instantiating and normalizing it with the given arguments. | 
|  | /// | 
|  | /// This will assume the type can be instantiated with these arguments. | 
|  | pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { | 
|  | with(|cx| cx.def_ty_with_args(self.0, args)) | 
|  | } | 
|  |  | 
|  | pub fn is_box(&self) -> bool { | 
|  | with(|cx| cx.adt_is_box(*self)) | 
|  | } | 
|  |  | 
|  | pub fn is_simd(&self) -> bool { | 
|  | with(|cx| cx.adt_is_simd(*self)) | 
|  | } | 
|  |  | 
|  | /// The number of variants in this ADT. | 
|  | pub fn num_variants(&self) -> usize { | 
|  | with(|cx| cx.adt_variants_len(*self)) | 
|  | } | 
|  |  | 
|  | /// Retrieve the variants in this ADT. | 
|  | pub fn variants(&self) -> Vec<VariantDef> { | 
|  | self.variants_iter().collect() | 
|  | } | 
|  |  | 
|  | /// Iterate over the variants in this ADT. | 
|  | pub fn variants_iter(&self) -> impl Iterator<Item = VariantDef> { | 
|  | (0..self.num_variants()) | 
|  | .map(|idx| VariantDef { idx: VariantIdx::to_val(idx), adt_def: *self }) | 
|  | } | 
|  |  | 
|  | pub fn variant(&self, idx: VariantIdx) -> Option<VariantDef> { | 
|  | (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self }) | 
|  | } | 
|  |  | 
|  | pub fn repr(&self) -> ReprOptions { | 
|  | with(|cx| cx.adt_repr(*self)) | 
|  | } | 
|  |  | 
|  | pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr { | 
|  | with(|cx| cx.adt_discr_for_variant(*self, idx)) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub struct Discr { | 
|  | pub val: u128, | 
|  | pub ty: Ty, | 
|  | } | 
|  |  | 
|  | /// Definition of a variant, which can be either a struct / union field or an enum variant. | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] | 
|  | pub struct VariantDef { | 
|  | /// The variant index. | 
|  | /// | 
|  | /// ## Warning | 
|  | /// Do not access this field directly! | 
|  | pub idx: VariantIdx, | 
|  | /// The data type where this variant comes from. | 
|  | /// For now, we use this to retrieve information about the variant itself so we don't need to | 
|  | /// cache more information. | 
|  | /// | 
|  | /// ## Warning | 
|  | /// Do not access this field directly! | 
|  | pub adt_def: AdtDef, | 
|  | } | 
|  |  | 
|  | impl VariantDef { | 
|  | pub fn name(&self) -> Symbol { | 
|  | with(|cx| cx.variant_name(*self)) | 
|  | } | 
|  |  | 
|  | /// Retrieve all the fields in this variant. | 
|  | // We expect user to cache this and use it directly since today it is expensive to generate all | 
|  | // fields name. | 
|  | pub fn fields(&self) -> Vec<FieldDef> { | 
|  | with(|cx| cx.variant_fields(*self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct FieldDef { | 
|  | /// The field definition. | 
|  | /// | 
|  | /// ## Warning | 
|  | /// Do not access this field directly! This is public for the compiler to have access to it. | 
|  | pub def: DefId, | 
|  |  | 
|  | /// The field name. | 
|  | pub name: Symbol, | 
|  | } | 
|  |  | 
|  | impl FieldDef { | 
|  | /// Retrieve the type of this field instantiating and normalizing it with the given arguments. | 
|  | /// | 
|  | /// This will assume the type can be instantiated with these arguments. | 
|  | pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { | 
|  | with(|cx| cx.def_ty_with_args(self.def, args)) | 
|  | } | 
|  |  | 
|  | /// Retrieve the type of this field. | 
|  | pub fn ty(&self) -> Ty { | 
|  | with(|cx| cx.def_ty(self.def)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Display for AdtKind { | 
|  | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 
|  | f.write_str(match self { | 
|  | AdtKind::Enum => "enum", | 
|  | AdtKind::Union => "union", | 
|  | AdtKind::Struct => "struct", | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl AdtKind { | 
|  | pub fn is_enum(&self) -> bool { | 
|  | matches!(self, AdtKind::Enum) | 
|  | } | 
|  |  | 
|  | pub fn is_struct(&self) -> bool { | 
|  | matches!(self, AdtKind::Struct) | 
|  | } | 
|  |  | 
|  | pub fn is_union(&self) -> bool { | 
|  | matches!(self, AdtKind::Union) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub AliasDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | /// A trait's definition. | 
|  | #[derive(Serialize)] | 
|  | pub TraitDef; | 
|  | } | 
|  |  | 
|  | impl_crate_def_items! { | 
|  | TraitDef; | 
|  | } | 
|  |  | 
|  | impl TraitDef { | 
|  | pub fn declaration(trait_def: &TraitDef) -> TraitDecl { | 
|  | with(|cx| cx.trait_decl(trait_def)) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub GenericDef; | 
|  | } | 
|  |  | 
|  | crate_def_with_ty! { | 
|  | #[derive(Serialize)] | 
|  | pub ConstDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | /// A trait impl definition. | 
|  | #[derive(Serialize)] | 
|  | pub ImplDef; | 
|  | } | 
|  |  | 
|  | impl_crate_def_items! { | 
|  | ImplDef; | 
|  | } | 
|  |  | 
|  | impl ImplDef { | 
|  | /// Retrieve information about this implementation. | 
|  | pub fn trait_impl(&self) -> ImplTrait { | 
|  | with(|cx| cx.trait_impl(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub RegionDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub CoroutineWitnessDef; | 
|  | } | 
|  |  | 
|  | /// A list of generic arguments. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct GenericArgs(pub Vec<GenericArgKind>); | 
|  |  | 
|  | impl std::ops::Index<ParamTy> for GenericArgs { | 
|  | type Output = Ty; | 
|  |  | 
|  | fn index(&self, index: ParamTy) -> &Self::Output { | 
|  | self.0[index.index as usize].expect_ty() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl std::ops::Index<ParamConst> for GenericArgs { | 
|  | type Output = TyConst; | 
|  |  | 
|  | fn index(&self, index: ParamConst) -> &Self::Output { | 
|  | self.0[index.index as usize].expect_const() | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum GenericArgKind { | 
|  | Lifetime(Region), | 
|  | Type(Ty), | 
|  | Const(TyConst), | 
|  | } | 
|  |  | 
|  | impl GenericArgKind { | 
|  | /// Panic if this generic argument is not a type, otherwise | 
|  | /// return the type. | 
|  | #[track_caller] | 
|  | pub fn expect_ty(&self) -> &Ty { | 
|  | match self { | 
|  | GenericArgKind::Type(ty) => ty, | 
|  | _ => panic!("{self:?}"), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Panic if this generic argument is not a const, otherwise | 
|  | /// return the const. | 
|  | #[track_caller] | 
|  | pub fn expect_const(&self) -> &TyConst { | 
|  | match self { | 
|  | GenericArgKind::Const(c) => c, | 
|  | _ => panic!("{self:?}"), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Return the generic argument type if applicable, otherwise return `None`. | 
|  | pub fn ty(&self) -> Option<&Ty> { | 
|  | match self { | 
|  | GenericArgKind::Type(ty) => Some(ty), | 
|  | _ => None, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum TermKind { | 
|  | Type(Ty), | 
|  | Const(TyConst), | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum AliasKind { | 
|  | Projection, | 
|  | Inherent, | 
|  | Opaque, | 
|  | Free, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct AliasTy { | 
|  | pub def_id: AliasDef, | 
|  | pub args: GenericArgs, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct AliasTerm { | 
|  | pub def_id: AliasDef, | 
|  | pub args: GenericArgs, | 
|  | } | 
|  |  | 
|  | pub type PolyFnSig = Binder<FnSig>; | 
|  |  | 
|  | impl PolyFnSig { | 
|  | /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. | 
|  | /// | 
|  | /// NB: this doesn't handle virtual calls - those should use `Instance::fn_abi` | 
|  | /// instead, where the instance is an `InstanceKind::Virtual`. | 
|  | pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> { | 
|  | with(|cx| cx.fn_ptr_abi(self)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct FnSig { | 
|  | pub inputs_and_output: Vec<Ty>, | 
|  | pub c_variadic: bool, | 
|  | pub safety: Safety, | 
|  | pub abi: Abi, | 
|  | } | 
|  |  | 
|  | impl FnSig { | 
|  | pub fn output(&self) -> Ty { | 
|  | self.inputs_and_output[self.inputs_and_output.len() - 1] | 
|  | } | 
|  |  | 
|  | pub fn inputs(&self) -> &[Ty] { | 
|  | &self.inputs_and_output[..self.inputs_and_output.len() - 1] | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, PartialEq, Eq, Debug, Serialize)] | 
|  | pub enum Abi { | 
|  | Rust, | 
|  | C { unwind: bool }, | 
|  | Cdecl { unwind: bool }, | 
|  | Stdcall { unwind: bool }, | 
|  | Fastcall { unwind: bool }, | 
|  | Vectorcall { unwind: bool }, | 
|  | Thiscall { unwind: bool }, | 
|  | Aapcs { unwind: bool }, | 
|  | Win64 { unwind: bool }, | 
|  | SysV64 { unwind: bool }, | 
|  | PtxKernel, | 
|  | Msp430Interrupt, | 
|  | X86Interrupt, | 
|  | GpuKernel, | 
|  | EfiApi, | 
|  | AvrInterrupt, | 
|  | AvrNonBlockingInterrupt, | 
|  | CCmseNonSecureCall, | 
|  | CCmseNonSecureEntry, | 
|  | System { unwind: bool }, | 
|  | RustCall, | 
|  | Unadjusted, | 
|  | RustCold, | 
|  | RiscvInterruptM, | 
|  | RiscvInterruptS, | 
|  | RustInvalid, | 
|  | Custom, | 
|  | } | 
|  |  | 
|  | /// A binder represents a possibly generic type and its bound vars. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct Binder<T> { | 
|  | pub value: T, | 
|  | pub bound_vars: Vec<BoundVariableKind>, | 
|  | } | 
|  |  | 
|  | impl<T> Binder<T> { | 
|  | /// Create a new binder with the given bound vars. | 
|  | pub fn bind_with_vars(value: T, bound_vars: Vec<BoundVariableKind>) -> Self { | 
|  | Binder { value, bound_vars } | 
|  | } | 
|  |  | 
|  | /// Create a new binder with no bounded variable. | 
|  | pub fn dummy(value: T) -> Self { | 
|  | Binder { value, bound_vars: vec![] } | 
|  | } | 
|  |  | 
|  | pub fn skip_binder(self) -> T { | 
|  | self.value | 
|  | } | 
|  |  | 
|  | pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> | 
|  | where | 
|  | F: FnOnce(&T) -> U, | 
|  | { | 
|  | let Binder { value, bound_vars } = self; | 
|  | let new_value = f(value); | 
|  | Binder { value: new_value, bound_vars: bound_vars.clone() } | 
|  | } | 
|  |  | 
|  | pub fn map_bound<F, U>(self, f: F) -> Binder<U> | 
|  | where | 
|  | F: FnOnce(T) -> U, | 
|  | { | 
|  | let Binder { value, bound_vars } = self; | 
|  | let new_value = f(value); | 
|  | Binder { value: new_value, bound_vars } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct EarlyBinder<T> { | 
|  | pub value: T, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum BoundVariableKind { | 
|  | Ty(BoundTyKind), | 
|  | Region(BoundRegionKind), | 
|  | Const, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, PartialEq, Eq, Debug, Serialize)] | 
|  | pub enum BoundTyKind { | 
|  | Anon, | 
|  | Param(ParamDef, String), | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum BoundRegionKind { | 
|  | BrAnon, | 
|  | BrNamed(BrNamedDef, String), | 
|  | BrEnv, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum DynKind { | 
|  | Dyn, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum ExistentialPredicate { | 
|  | Trait(ExistentialTraitRef), | 
|  | Projection(ExistentialProjection), | 
|  | AutoTrait(TraitDef), | 
|  | } | 
|  |  | 
|  | /// An existential reference to a trait where `Self` is not included. | 
|  | /// | 
|  | /// The `generic_args` will include any other known argument. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct ExistentialTraitRef { | 
|  | pub def_id: TraitDef, | 
|  | pub generic_args: GenericArgs, | 
|  | } | 
|  |  | 
|  | impl Binder<ExistentialTraitRef> { | 
|  | pub fn with_self_ty(&self, self_ty: Ty) -> Binder<TraitRef> { | 
|  | self.map_bound_ref(|trait_ref| trait_ref.with_self_ty(self_ty)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ExistentialTraitRef { | 
|  | pub fn with_self_ty(&self, self_ty: Ty) -> TraitRef { | 
|  | TraitRef::new(self.def_id, self_ty, &self.generic_args) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct ExistentialProjection { | 
|  | pub def_id: TraitDef, | 
|  | pub generic_args: GenericArgs, | 
|  | pub term: TermKind, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct ParamTy { | 
|  | pub index: u32, | 
|  | pub name: String, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct BoundTy { | 
|  | pub var: usize, | 
|  | pub kind: BoundTyKind, | 
|  | } | 
|  |  | 
|  | pub type Bytes = Vec<Option<u8>>; | 
|  |  | 
|  | /// Size in bytes. | 
|  | pub type Size = usize; | 
|  |  | 
|  | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] | 
|  | pub struct Prov(pub AllocId); | 
|  |  | 
|  | pub type Align = u64; | 
|  | pub type Promoted = u32; | 
|  | pub type InitMaskMaterialized = Vec<u64>; | 
|  |  | 
|  | /// Stores the provenance information of pointers stored in memory. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] | 
|  | pub struct ProvenanceMap { | 
|  | /// Provenance in this map applies from the given offset for an entire pointer-size worth of | 
|  | /// bytes. Two entries in this map are always at least a pointer size apart. | 
|  | pub ptrs: Vec<(Size, Prov)>, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] | 
|  | pub struct Allocation { | 
|  | pub bytes: Bytes, | 
|  | pub provenance: ProvenanceMap, | 
|  | pub align: Align, | 
|  | pub mutability: Mutability, | 
|  | } | 
|  |  | 
|  | impl Allocation { | 
|  | /// Get a vector of bytes for an Allocation that has been fully initialized | 
|  | pub fn raw_bytes(&self) -> Result<Vec<u8>, Error> { | 
|  | self.bytes | 
|  | .iter() | 
|  | .copied() | 
|  | .collect::<Option<Vec<_>>>() | 
|  | .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes)) | 
|  | } | 
|  |  | 
|  | /// Read a uint value from the specified range. | 
|  | pub fn read_partial_uint(&self, range: Range<usize>) -> Result<u128, Error> { | 
|  | if range.end - range.start > 16 { | 
|  | return Err(error!("Allocation is bigger than largest integer")); | 
|  | } | 
|  | if range.end > self.bytes.len() { | 
|  | return Err(error!( | 
|  | "Range is out of bounds. Allocation length is `{}`, but requested range `{:?}`", | 
|  | self.bytes.len(), | 
|  | range | 
|  | )); | 
|  | } | 
|  | let raw = self.bytes[range] | 
|  | .iter() | 
|  | .copied() | 
|  | .collect::<Option<Vec<_>>>() | 
|  | .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))?; | 
|  | read_target_uint(&raw) | 
|  | } | 
|  |  | 
|  | /// Read this allocation and try to convert it to an unassigned integer. | 
|  | pub fn read_uint(&self) -> Result<u128, Error> { | 
|  | if self.bytes.len() > 16 { | 
|  | return Err(error!("Allocation is bigger than largest integer")); | 
|  | } | 
|  | let raw = self.raw_bytes()?; | 
|  | read_target_uint(&raw) | 
|  | } | 
|  |  | 
|  | /// Read this allocation and try to convert it to a signed integer. | 
|  | pub fn read_int(&self) -> Result<i128, Error> { | 
|  | if self.bytes.len() > 16 { | 
|  | return Err(error!("Allocation is bigger than largest integer")); | 
|  | } | 
|  | let raw = self.raw_bytes()?; | 
|  | read_target_int(&raw) | 
|  | } | 
|  |  | 
|  | /// Read this allocation and try to convert it to a boolean. | 
|  | pub fn read_bool(&self) -> Result<bool, Error> { | 
|  | match self.read_int()? { | 
|  | 0 => Ok(false), | 
|  | 1 => Ok(true), | 
|  | val => Err(error!("Unexpected value for bool: `{val}`")), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Read this allocation as a pointer and return whether it represents a `null` pointer. | 
|  | pub fn is_null(&self) -> Result<bool, Error> { | 
|  | let len = self.bytes.len(); | 
|  | let ptr_len = MachineInfo::target_pointer_width().bytes(); | 
|  | if len != ptr_len { | 
|  | return Err(error!("Expected width of pointer (`{ptr_len}`), but found: `{len}`")); | 
|  | } | 
|  | Ok(self.read_uint()? == 0 && self.provenance.ptrs.is_empty()) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum ConstantKind { | 
|  | Ty(TyConst), | 
|  | Allocated(Allocation), | 
|  | Unevaluated(UnevaluatedConst), | 
|  | Param(ParamConst), | 
|  | /// Store ZST constants. | 
|  | /// We have to special handle these constants since its type might be generic. | 
|  | ZeroSized, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct ParamConst { | 
|  | pub index: u32, | 
|  | pub name: String, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct UnevaluatedConst { | 
|  | pub def: ConstDef, | 
|  | pub args: GenericArgs, | 
|  | pub promoted: Option<Promoted>, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] | 
|  | pub enum TraitSpecializationKind { | 
|  | None, | 
|  | Marker, | 
|  | AlwaysApplicable, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct TraitDecl { | 
|  | pub def_id: TraitDef, | 
|  | pub safety: Safety, | 
|  | pub paren_sugar: bool, | 
|  | pub has_auto_impl: bool, | 
|  | pub is_marker: bool, | 
|  | pub is_coinductive: bool, | 
|  | pub skip_array_during_method_dispatch: bool, | 
|  | pub skip_boxed_slice_during_method_dispatch: bool, | 
|  | pub specialization_kind: TraitSpecializationKind, | 
|  | pub must_implement_one_of: Option<Vec<Ident>>, | 
|  | pub implement_via_object: bool, | 
|  | pub deny_explicit_impl: bool, | 
|  | } | 
|  |  | 
|  | impl TraitDecl { | 
|  | pub fn generics_of(&self) -> Generics { | 
|  | with(|cx| cx.generics_of(self.def_id.0)) | 
|  | } | 
|  |  | 
|  | pub fn predicates_of(&self) -> GenericPredicates { | 
|  | with(|cx| cx.predicates_of(self.def_id.0)) | 
|  | } | 
|  |  | 
|  | pub fn explicit_predicates_of(&self) -> GenericPredicates { | 
|  | with(|cx| cx.explicit_predicates_of(self.def_id.0)) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub type ImplTrait = EarlyBinder<TraitRef>; | 
|  |  | 
|  | /// A complete reference to a trait, i.e., one where `Self` is known. | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct TraitRef { | 
|  | pub def_id: TraitDef, | 
|  | /// The generic arguments for this definition. | 
|  | /// The first element must always be type, and it represents `Self`. | 
|  | args: GenericArgs, | 
|  | } | 
|  |  | 
|  | impl TraitRef { | 
|  | pub fn new(def_id: TraitDef, self_ty: Ty, gen_args: &GenericArgs) -> TraitRef { | 
|  | let mut args = vec![GenericArgKind::Type(self_ty)]; | 
|  | args.extend_from_slice(&gen_args.0); | 
|  | TraitRef { def_id, args: GenericArgs(args) } | 
|  | } | 
|  |  | 
|  | pub fn try_new(def_id: TraitDef, args: GenericArgs) -> Result<TraitRef, ()> { | 
|  | match &args.0[..] { | 
|  | [GenericArgKind::Type(_), ..] => Ok(TraitRef { def_id, args }), | 
|  | _ => Err(()), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn args(&self) -> &GenericArgs { | 
|  | &self.args | 
|  | } | 
|  |  | 
|  | pub fn self_ty(&self) -> Ty { | 
|  | let GenericArgKind::Type(self_ty) = self.args.0[0] else { | 
|  | panic!("Self must be a type, but found: {:?}", self.args.0[0]) | 
|  | }; | 
|  | self_ty | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct Generics { | 
|  | pub parent: Option<GenericDef>, | 
|  | pub parent_count: usize, | 
|  | pub params: Vec<GenericParamDef>, | 
|  | pub param_def_id_to_index: Vec<(GenericDef, u32)>, | 
|  | pub has_self: bool, | 
|  | pub has_late_bound_regions: Option<Span>, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum GenericParamDefKind { | 
|  | Lifetime, | 
|  | Type { has_default: bool, synthetic: bool }, | 
|  | Const { has_default: bool }, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct GenericParamDef { | 
|  | pub name: super::Symbol, | 
|  | pub def_id: GenericDef, | 
|  | pub index: u32, | 
|  | pub pure_wrt_drop: bool, | 
|  | pub kind: GenericParamDefKind, | 
|  | } | 
|  |  | 
|  | pub struct GenericPredicates { | 
|  | pub parent: Option<TraitDef>, | 
|  | pub predicates: Vec<(PredicateKind, Span)>, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum PredicateKind { | 
|  | Clause(ClauseKind), | 
|  | DynCompatible(TraitDef), | 
|  | SubType(SubtypePredicate), | 
|  | Coerce(CoercePredicate), | 
|  | ConstEquate(TyConst, TyConst), | 
|  | Ambiguous, | 
|  | AliasRelate(TermKind, TermKind, AliasRelationDirection), | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum ClauseKind { | 
|  | Trait(TraitPredicate), | 
|  | RegionOutlives(RegionOutlivesPredicate), | 
|  | TypeOutlives(TypeOutlivesPredicate), | 
|  | Projection(ProjectionPredicate), | 
|  | ConstArgHasType(TyConst, Ty), | 
|  | WellFormed(TermKind), | 
|  | ConstEvaluatable(TyConst), | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum ClosureKind { | 
|  | Fn, | 
|  | FnMut, | 
|  | FnOnce, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct SubtypePredicate { | 
|  | pub a: Ty, | 
|  | pub b: Ty, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct CoercePredicate { | 
|  | pub a: Ty, | 
|  | pub b: Ty, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum AliasRelationDirection { | 
|  | Equate, | 
|  | Subtype, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct TraitPredicate { | 
|  | pub trait_ref: TraitRef, | 
|  | pub polarity: PredicatePolarity, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct OutlivesPredicate<A, B>(pub A, pub B); | 
|  |  | 
|  | pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>; | 
|  | pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>; | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct ProjectionPredicate { | 
|  | pub projection_term: AliasTerm, | 
|  | pub term: TermKind, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum ImplPolarity { | 
|  | Positive, | 
|  | Negative, | 
|  | Reservation, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum PredicatePolarity { | 
|  | Positive, | 
|  | Negative, | 
|  | } | 
|  |  | 
|  | macro_rules! index_impl { | 
|  | ($name:ident) => { | 
|  | impl crate::IndexedVal for $name { | 
|  | fn to_val(index: usize) -> Self { | 
|  | $name(index) | 
|  | } | 
|  | fn to_index(&self) -> usize { | 
|  | self.0 | 
|  | } | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | index_impl!(TyConstId); | 
|  | index_impl!(MirConstId); | 
|  | index_impl!(Ty); | 
|  | index_impl!(Span); | 
|  |  | 
|  | /// The source-order index of a variant in a type. | 
|  | /// | 
|  | /// For example, in the following types, | 
|  | /// ```ignore(illustrative) | 
|  | /// enum Demo1 { | 
|  | ///    Variant0 { a: bool, b: i32 }, | 
|  | ///    Variant1 { c: u8, d: u64 }, | 
|  | /// } | 
|  | /// struct Demo2 { e: u8, f: u16, g: u8 } | 
|  | /// ``` | 
|  | /// `a` is in the variant with the `VariantIdx` of `0`, | 
|  | /// `c` is in the variant with the `VariantIdx` of `1`, and | 
|  | /// `g` is in the variant with the `VariantIdx` of `0`. | 
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] | 
|  | pub struct VariantIdx(usize); | 
|  |  | 
|  | index_impl!(VariantIdx); | 
|  |  | 
|  | crate_def! { | 
|  | /// Hold information about an Opaque definition, particularly useful in `RPITIT`. | 
|  | #[derive(Serialize)] | 
|  | pub OpaqueDef; | 
|  | } | 
|  |  | 
|  | crate_def! { | 
|  | #[derive(Serialize)] | 
|  | pub AssocDef; | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub struct AssocItem { | 
|  | pub def_id: AssocDef, | 
|  | pub kind: AssocKind, | 
|  | pub container: AssocItemContainer, | 
|  |  | 
|  | /// If this is an item in an impl of a trait then this is the `DefId` of | 
|  | /// the associated item on the trait that this implements. | 
|  | pub trait_item_def_id: Option<AssocDef>, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, PartialEq, Debug, Eq, Serialize)] | 
|  | pub enum AssocTypeData { | 
|  | Normal(Symbol), | 
|  | /// The associated type comes from an RPITIT. It has no name, and the | 
|  | /// `ImplTraitInTraitData` provides additional information about its | 
|  | /// source. | 
|  | Rpitit(ImplTraitInTraitData), | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum AssocKind { | 
|  | Const { name: Symbol }, | 
|  | Fn { name: Symbol, has_self: bool }, | 
|  | Type { data: AssocTypeData }, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | 
|  | pub enum AssocItemContainer { | 
|  | Trait, | 
|  | Impl, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] | 
|  | pub enum ImplTraitInTraitData { | 
|  | Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef }, | 
|  | Impl { fn_def_id: FnDef }, | 
|  | } | 
|  |  | 
|  | impl AssocItem { | 
|  | pub fn is_impl_trait_in_trait(&self) -> bool { | 
|  | matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) }) | 
|  | } | 
|  | } |