diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_type_ir/src/lib.rs | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_type_ir/src/lib.rs')
-rw-r--r-- | compiler/rustc_type_ir/src/lib.rs | 592 |
1 files changed, 21 insertions, 571 deletions
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 83401b65c..e8785fff2 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,310 +1,55 @@ #![feature(associated_type_defaults)] #![feature(fmt_helpers_for_derive)] +#![feature(get_mut_unchecked)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(unwrap_infallible)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] +extern crate self as rustc_type_ir; + #[macro_use] extern crate bitflags; #[macro_use] extern crate rustc_macros; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; -use smallvec::SmallVec; use std::fmt; -use std::fmt::Debug; use std::hash::Hash; -use std::mem::discriminant; pub mod codec; pub mod fold; -pub mod sty; pub mod ty_info; +pub mod ty_kind; pub mod visit; #[macro_use] mod macros; -mod structural_impls; - +mod canonical; +mod const_kind; +mod debug; +mod flags; +mod interner; +mod predicate_kind; +mod region_kind; + +pub use canonical::*; pub use codec::*; -pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; -pub use sty::*; +pub use const_kind::*; +pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx}; +pub use flags::*; +pub use interner::*; +pub use predicate_kind::*; +pub use region_kind::*; pub use ty_info::*; +pub use ty_kind::*; /// Needed so we can use #[derive(HashStable_Generic)] pub trait HashStableContext {} -pub trait Interner: Sized { - type AdtDef: Clone + Debug + Hash + Ord; - type GenericArgsRef: Clone - + DebugWithInfcx<Self> - + Hash - + Ord - + IntoIterator<Item = Self::GenericArg>; - type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord; - type DefId: Clone + Debug + Hash + Ord; - type Binder<T>; - type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord; - type Const: Clone + DebugWithInfcx<Self> + Hash + Ord; - type Region: Clone + DebugWithInfcx<Self> + Hash + Ord; - type Predicate; - type TypeAndMut: Clone + Debug + Hash + Ord; - type Mutability: Clone + Debug + Hash + Ord; - type Movability: Clone + Debug + Hash + Ord; - type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord; - type ListBinderExistentialPredicate: Clone + DebugWithInfcx<Self> + Hash + Ord; - type BinderListTy: Clone + DebugWithInfcx<Self> + Hash + Ord; - type ListTy: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>; - type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord; - type ParamTy: Clone + Debug + Hash + Ord; - type BoundTy: Clone + Debug + Hash + Ord; - type PlaceholderType: Clone + Debug + Hash + Ord; - type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord; - type ErrorGuaranteed: Clone + Debug + Hash + Ord; - type PredicateKind: Clone + Debug + Hash + PartialEq + Eq; - type AllocId: Clone + Debug + Hash + Ord; - - type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord; - type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord; - type PlaceholderConst: Clone + Debug + Hash + Ord; - type ParamConst: Clone + Debug + Hash + Ord; - type BoundConst: Clone + Debug + Hash + Ord; - type ValueConst: Clone + Debug + Hash + Ord; - type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord; - - type EarlyBoundRegion: Clone + Debug + Hash + Ord; - type BoundRegion: Clone + Debug + Hash + Ord; - type FreeRegion: Clone + Debug + Hash + Ord; - type RegionVid: Clone + DebugWithInfcx<Self> + Hash + Ord; - type PlaceholderRegion: Clone + Debug + Hash + Ord; - - fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability); - fn mutability_is_mut(mutbl: Self::Mutability) -> bool; -} - -/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` -/// that produces `T` items. You could combine them with -/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the -/// `Vec`. -/// -/// This trait allows for faster implementations, intended for cases where the -/// number of items produced by the iterator is small. There is a blanket impl -/// for `T` items, but there is also a fallible impl for `Result<T, E>` items. -pub trait CollectAndApply<T, R>: Sized { - type Output; - - /// Produce a result of type `Self::Output` from `iter`. The result will - /// typically be produced by applying `f` on the elements produced by - /// `iter`, though this may not happen in some impls, e.g. if an error - /// occurred during iteration. - fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output - where - I: Iterator<Item = Self>, - F: FnOnce(&[T]) -> R; -} - -/// The blanket impl that always collects all elements and applies `f`. -impl<T, R> CollectAndApply<T, R> for T { - type Output = R; - - /// Equivalent to `f(&iter.collect::<Vec<_>>())`. - fn collect_and_apply<I, F>(mut iter: I, f: F) -> R - where - I: Iterator<Item = T>, - F: FnOnce(&[T]) -> R, - { - // This code is hot enough that it's worth specializing for the most - // common length lists, to avoid the overhead of `SmallVec` creation. - // Lengths 0, 1, and 2 typically account for ~95% of cases. If - // `size_hint` is incorrect a panic will occur via an `unwrap` or an - // `assert`. - match iter.size_hint() { - (0, Some(0)) => { - assert!(iter.next().is_none()); - f(&[]) - } - (1, Some(1)) => { - let t0 = iter.next().unwrap(); - assert!(iter.next().is_none()); - f(&[t0]) - } - (2, Some(2)) => { - let t0 = iter.next().unwrap(); - let t1 = iter.next().unwrap(); - assert!(iter.next().is_none()); - f(&[t0, t1]) - } - _ => f(&iter.collect::<SmallVec<[_; 8]>>()), - } - } -} - -/// A fallible impl that will fail, without calling `f`, if there are any -/// errors during collection. -impl<T, R, E> CollectAndApply<T, R> for Result<T, E> { - type Output = Result<R, E>; - - /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`. - fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E> - where - I: Iterator<Item = Result<T, E>>, - F: FnOnce(&[T]) -> R, - { - // This code is hot enough that it's worth specializing for the most - // common length lists, to avoid the overhead of `SmallVec` creation. - // Lengths 0, 1, and 2 typically account for ~95% of cases. If - // `size_hint` is incorrect a panic will occur via an `unwrap` or an - // `assert`, unless a failure happens first, in which case the result - // will be an error anyway. - Ok(match iter.size_hint() { - (0, Some(0)) => { - assert!(iter.next().is_none()); - f(&[]) - } - (1, Some(1)) => { - let t0 = iter.next().unwrap()?; - assert!(iter.next().is_none()); - f(&[t0]) - } - (2, Some(2)) => { - let t0 = iter.next().unwrap()?; - let t1 = iter.next().unwrap()?; - assert!(iter.next().is_none()); - f(&[t0, t1]) - } - _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?), - }) - } -} - -bitflags! { - /// Flags that we track on types. These flags are propagated upwards - /// through the type during type construction, so that we can quickly check - /// whether the type has various kinds of types in it without recursing - /// over the type itself. - pub struct TypeFlags: u32 { - // Does this have parameters? Used to determine whether substitution is - // required. - /// Does this have `Param`? - const HAS_TY_PARAM = 1 << 0; - /// Does this have `ReEarlyBound`? - const HAS_RE_PARAM = 1 << 1; - /// Does this have `ConstKind::Param`? - const HAS_CT_PARAM = 1 << 2; - - const HAS_PARAM = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits; - - /// Does this have `Infer`? - const HAS_TY_INFER = 1 << 3; - /// Does this have `ReVar`? - const HAS_RE_INFER = 1 << 4; - /// Does this have `ConstKind::Infer`? - const HAS_CT_INFER = 1 << 5; - - /// Does this have inference variables? Used to determine whether - /// inference is required. - const HAS_INFER = TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits - | TypeFlags::HAS_CT_INFER.bits; - - /// Does this have `Placeholder`? - const HAS_TY_PLACEHOLDER = 1 << 6; - /// Does this have `RePlaceholder`? - const HAS_RE_PLACEHOLDER = 1 << 7; - /// Does this have `ConstKind::Placeholder`? - const HAS_CT_PLACEHOLDER = 1 << 8; - - /// Does this have placeholders? - const HAS_PLACEHOLDER = TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_RE_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits; - - /// `true` if there are "names" of regions and so forth - /// that are local to a particular fn/inferctxt - const HAS_FREE_LOCAL_REGIONS = 1 << 9; - - /// `true` if there are "names" of types and regions and so forth - /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits - | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_CT_INFER.bits - | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits - // We consider 'freshened' types and constants - // to depend on a particular fn. - // The freshening process throws away information, - // which can make things unsuitable for use in a global - // cache. Note that there is no 'fresh lifetime' flag - - // freshening replaces all lifetimes with `ReErased`, - // which is different from how types/const are freshened. - | TypeFlags::HAS_TY_FRESH.bits - | TypeFlags::HAS_CT_FRESH.bits - | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits - | TypeFlags::HAS_RE_ERASED.bits; - - /// Does this have `Projection`? - const HAS_TY_PROJECTION = 1 << 10; - /// Does this have `Inherent`? - const HAS_TY_INHERENT = 1 << 11; - /// Does this have `Opaque`? - const HAS_TY_OPAQUE = 1 << 12; - /// Does this have `ConstKind::Unevaluated`? - const HAS_CT_PROJECTION = 1 << 13; - - /// Could this type be normalized further? - const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits - | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_TY_INHERENT.bits - | TypeFlags::HAS_CT_PROJECTION.bits; - - /// Is an error type/const reachable? - const HAS_ERROR = 1 << 14; - - /// Does this have any region that "appears free" in the type? - /// Basically anything but `ReLateBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 15; - - /// Does this have any `ReLateBound` regions? - const HAS_RE_LATE_BOUND = 1 << 16; - /// Does this have any `Bound` types? - const HAS_TY_LATE_BOUND = 1 << 17; - /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_LATE_BOUND = 1 << 18; - /// Does this have any bound variables? - /// Used to check if a global bound is safe to evaluate. - const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits - | TypeFlags::HAS_TY_LATE_BOUND.bits - | TypeFlags::HAS_CT_LATE_BOUND.bits; - - /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 19; - - /// Does this value have parameters/placeholders/inference variables which could be - /// replaced later, in a way that would change the results of `impl` specialization? - const STILL_FURTHER_SPECIALIZABLE = 1 << 20; - - /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 21; - - /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 22; - - /// Does this have `Generator` or `GeneratorWitness`? - const HAS_TY_GENERATOR = 1 << 23; - - /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 24; - } -} - rustc_index::newtype_index! { /// A [De Bruijn index][dbi] is a standard means of representing /// regions (and perhaps later types) in a higher-ranked setting. In @@ -428,259 +173,6 @@ pub fn debug_bound_var<T: std::fmt::Write>( } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] -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", - } - } - - 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, - } - } -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[derive(Encodable, Decodable, HashStable_Generic)] -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", - } - } - - 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, - } - } -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] -pub enum FloatTy { - F32, - F64, -} - -impl FloatTy { - pub fn name_str(self) -> &'static str { - match self { - FloatTy::F32 => "f32", - FloatTy::F64 => "f64", - } - } - - pub fn bit_width(self) -> u64 { - match self { - FloatTy::F32 => 32, - FloatTy::F64 => 64, - } - } -} - -#[derive(Clone, Copy, PartialEq, Eq)] -pub enum IntVarValue { - IntType(IntTy), - UintType(UintTy), -} - -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct FloatVarValue(pub FloatTy); - -rustc_index::newtype_index! { - /// A **ty**pe **v**ariable **ID**. - #[debug_format = "?{}t"] - pub struct TyVid {} -} - -rustc_index::newtype_index! { - /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. - #[debug_format = "?{}i"] - pub struct IntVid {} -} - -rustc_index::newtype_index! { - /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. - #[debug_format = "?{}f"] - pub struct FloatVid {} -} - -/// A placeholder for a type that hasn't been inferred yet. -/// -/// E.g., if we have an empty array (`[]`), then we create a fresh -/// type variable for the element type since we won't know until it's -/// used what the element type is supposed to be. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub enum InferTy { - /// A type variable. - TyVar(TyVid), - /// An integral type variable (`{integer}`). - /// - /// These are created when the compiler sees an integer literal like - /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.). - /// We don't know until it's used what type it's supposed to be, so - /// we create a fresh type variable. - IntVar(IntVid), - /// A floating-point type variable (`{float}`). - /// - /// These are created when the compiler sees an float literal like - /// `1.0` that could be either an `f32` or an `f64`. - /// We don't know until it's used what type it's supposed to be, so - /// we create a fresh type variable. - FloatVar(FloatVid), - - /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement - /// for an unbound type variable. This is convenient for caching etc. See - /// `rustc_infer::infer::freshen` for more details. - /// - /// Compare with [`TyVar`][Self::TyVar]. - FreshTy(u32), - /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar]. - FreshIntTy(u32), - /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar]. - FreshFloatTy(u32), -} - -/// Raw `TyVid` are used as the unification key for `sub_relations`; -/// they carry no values. -impl UnifyKey for TyVid { - type Value = (); - #[inline] - fn index(&self) -> u32 { - self.as_u32() - } - #[inline] - fn from_index(i: u32) -> TyVid { - TyVid::from_u32(i) - } - fn tag() -> &'static str { - "TyVid" - } -} - -impl EqUnifyValue for IntVarValue {} - -impl UnifyKey for IntVid { - type Value = Option<IntVarValue>; - #[inline] // make this function eligible for inlining - it is quite hot. - fn index(&self) -> u32 { - self.as_u32() - } - #[inline] - fn from_index(i: u32) -> IntVid { - IntVid::from_u32(i) - } - fn tag() -> &'static str { - "IntVid" - } -} - -impl EqUnifyValue for FloatVarValue {} - -impl UnifyKey for FloatVid { - type Value = Option<FloatVarValue>; - #[inline] - fn index(&self) -> u32 { - self.as_u32() - } - #[inline] - fn from_index(i: u32) -> FloatVid { - FloatVid::from_u32(i) - } - fn tag() -> &'static str { - "FloatVid" - } -} - #[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)] #[rustc_pass_by_value] pub enum Variance { @@ -750,34 +242,6 @@ impl Variance { } } -impl<CTX> HashStable<CTX> for InferTy { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - use InferTy::*; - discriminant(self).hash_stable(ctx, hasher); - match self { - TyVar(_) | IntVar(_) | FloatVar(_) => { - panic!("type variables should not be hashed: {self:?}") - } - FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher), - } - } -} - -impl fmt::Debug for IntVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - IntVarValue::IntType(ref v) => v.fmt(f), - IntVarValue::UintType(ref v) => v.fmt(f), - } - } -} - -impl fmt::Debug for FloatVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - impl fmt::Debug for Variance { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { @@ -789,20 +253,6 @@ impl fmt::Debug for Variance { } } -impl fmt::Display for InferTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use InferTy::*; - match *self { - TyVar(_) => write!(f, "_"), - IntVar(_) => write!(f, "{}", "{integer}"), - FloatVar(_) => write!(f, "{}", "{float}"), - FreshTy(v) => write!(f, "FreshTy({v})"), - FreshIntTy(v) => write!(f, "FreshIntTy({v})"), - FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"), - } - } -} - rustc_index::newtype_index! { /// "Universes" are used during type- and trait-checking in the /// presence of `for<..>` binders to control what sets of names are |