diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /vendor/chalk-ir-0.80.0/src/lib.rs | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chalk-ir-0.80.0/src/lib.rs')
-rw-r--r-- | vendor/chalk-ir-0.80.0/src/lib.rs | 3077 |
1 files changed, 0 insertions, 3077 deletions
diff --git a/vendor/chalk-ir-0.80.0/src/lib.rs b/vendor/chalk-ir-0.80.0/src/lib.rs deleted file mode 100644 index 9376a6563..000000000 --- a/vendor/chalk-ir-0.80.0/src/lib.rs +++ /dev/null @@ -1,3077 +0,0 @@ -//! Defines the IR for types and logical predicates. - -#![deny(rust_2018_idioms)] -#![warn(missing_docs)] - -// Allows macros to refer to this crate as `::chalk_ir` -extern crate self as chalk_ir; - -use crate::cast::{Cast, CastTo, Caster}; -use crate::fold::shift::Shift; -use crate::fold::{Fold, Folder, Subst, SuperFold}; -use crate::visit::{SuperVisit, Visit, VisitExt, Visitor}; -use chalk_derive::{Fold, HasInterner, SuperVisit, Visit, Zip}; -use std::marker::PhantomData; -use std::ops::ControlFlow; - -pub use crate::debug::SeparatorTraitRef; -#[macro_use(bitflags)] -extern crate bitflags; -/// Uninhabited (empty) type, used in combination with `PhantomData`. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Void {} - -/// Many of our internal operations (e.g., unification) are an attempt -/// to perform some operation which may not complete. -pub type Fallible<T> = Result<T, NoSolution>; - -/// A combination of `Fallible` and `Floundered`. -pub enum FallibleOrFloundered<T> { - /// Success - Ok(T), - /// No solution. See `chalk_ir::NoSolution`. - NoSolution, - /// Floundered. See `chalk_ir::Floundered`. - Floundered, -} - -/// Indicates that the attempted operation has "no solution" -- i.e., -/// cannot be performed. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct NoSolution; - -/// Indicates that the complete set of program clauses for this goal -/// cannot be enumerated. -pub struct Floundered; - -macro_rules! impl_debugs { - ($($id:ident), *) => { - $( - impl<I: Interner> std::fmt::Debug for $id<I> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - write!(fmt, "{}({:?})", stringify!($id), self.0) - } - } - )* - }; -} - -#[macro_use] -pub mod zip; - -#[macro_use] -pub mod fold; - -#[macro_use] -pub mod visit; - -pub mod cast; - -pub mod interner; -use interner::{HasInterner, Interner}; - -pub mod could_match; -pub mod debug; - -/// Variance -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum Variance { - /// a <: b - Covariant, - /// a == b - Invariant, - /// b <: a - Contravariant, -} - -impl Variance { - /// `a.xform(b)` combines the variance of a context with the - /// variance of a type with the following meaning. If we are in a - /// context with variance `a`, and we encounter a type argument in - /// a position with variance `b`, then `a.xform(b)` is the new - /// variance with which the argument appears. - /// - /// Example 1: - /// - /// ```ignore - /// *mut Vec<i32> - /// ``` - /// - /// Here, the "ambient" variance starts as covariant. `*mut T` is - /// invariant with respect to `T`, so the variance in which the - /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which - /// yields `Invariant`. Now, the type `Vec<T>` is covariant with - /// respect to its type argument `T`, and hence the variance of - /// the `i32` here is `Invariant.xform(Covariant)`, which results - /// (again) in `Invariant`. - /// - /// Example 2: - /// - /// ```ignore - /// fn(*const Vec<i32>, *mut Vec<i32) - /// ``` - /// - /// The ambient variance is covariant. A `fn` type is - /// contravariant with respect to its parameters, so the variance - /// within which both pointer types appear is - /// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const - /// T` is covariant with respect to `T`, so the variance within - /// which the first `Vec<i32>` appears is - /// `Contravariant.xform(Covariant)` or `Contravariant`. The same - /// is true for its `i32` argument. In the `*mut T` case, the - /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`, - /// and hence the outermost type is `Invariant` with respect to - /// `Vec<i32>` (and its `i32` argument). - /// - /// Source: Figure 1 of "Taming the Wildcards: - /// Combining Definition- and Use-Site Variance" published in PLDI'11. - /// (Doc from rustc) - pub fn xform(self, other: Variance) -> Variance { - match (self, other) { - (Variance::Invariant, _) => Variance::Invariant, - (_, Variance::Invariant) => Variance::Invariant, - (_, Variance::Covariant) => self, - (Variance::Covariant, Variance::Contravariant) => Variance::Contravariant, - (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant, - } - } - - /// Converts `Covariant` into `Contravariant` and vice-versa. `Invariant` - /// stays the same. - pub fn invert(self) -> Variance { - match self { - Variance::Invariant => Variance::Invariant, - Variance::Covariant => Variance::Contravariant, - Variance::Contravariant => Variance::Covariant, - } - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -/// The set of assumptions we've made so far, and the current number of -/// universal (forall) quantifiers we're within. -pub struct Environment<I: Interner> { - /// The clauses in the environment. - pub clauses: ProgramClauses<I>, -} - -impl<I: Interner> Copy for Environment<I> where I::InternedProgramClauses: Copy {} - -impl<I: Interner> Environment<I> { - /// Creates a new environment. - pub fn new(interner: I) -> Self { - Environment { - clauses: ProgramClauses::empty(interner), - } - } - - /// Adds (an iterator of) clauses to the environment. - pub fn add_clauses<II>(&self, interner: I, clauses: II) -> Self - where - II: IntoIterator<Item = ProgramClause<I>>, - { - let mut env = self.clone(); - env.clauses = - ProgramClauses::from_iter(interner, env.clauses.iter(interner).cloned().chain(clauses)); - env - } - - /// True if any of the clauses in the environment have a consequence of `Compatible`. - /// Panics if the conditions or constraints of that clause are not empty. - pub fn has_compatible_clause(&self, interner: I) -> bool { - self.clauses.as_slice(interner).iter().any(|c| { - let ProgramClauseData(implication) = c.data(interner); - match implication.skip_binders().consequence { - DomainGoal::Compatible => { - // We currently don't generate `Compatible` with any conditions or constraints - // If this was needed, for whatever reason, then a third "yes, but must evaluate" - // return value would have to be added. - assert!(implication.skip_binders().conditions.is_empty(interner)); - assert!(implication.skip_binders().constraints.is_empty(interner)); - true - } - _ => false, - } - }) - } -} - -/// A goal with an environment to solve it in. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)] -#[allow(missing_docs)] -pub struct InEnvironment<G: HasInterner> { - pub environment: Environment<G::Interner>, - pub goal: G, -} - -impl<G: HasInterner<Interner = I> + Copy, I: Interner> Copy for InEnvironment<G> where - I::InternedProgramClauses: Copy -{ -} - -impl<G: HasInterner> InEnvironment<G> { - /// Creates a new environment/goal pair. - pub fn new(environment: &Environment<G::Interner>, goal: G) -> Self { - InEnvironment { - environment: environment.clone(), - goal, - } - } - - /// Maps the goal without touching the environment. - pub fn map<OP, H>(self, op: OP) -> InEnvironment<H> - where - OP: FnOnce(G) -> H, - H: HasInterner<Interner = G::Interner>, - { - InEnvironment { - environment: self.environment, - goal: op(self.goal), - } - } -} - -impl<G: HasInterner> HasInterner for InEnvironment<G> { - type Interner = G::Interner; -} - -/// Different signed int types. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[allow(missing_docs)] -pub enum IntTy { - Isize, - I8, - I16, - I32, - I64, - I128, -} - -/// Different unsigned int types. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[allow(missing_docs)] -pub enum UintTy { - Usize, - U8, - U16, - U32, - U64, - U128, -} - -/// Different kinds of float types. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[allow(missing_docs)] -pub enum FloatTy { - F32, - F64, -} - -/// Types of scalar values. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[allow(missing_docs)] -pub enum Scalar { - Bool, - Char, - Int(IntTy), - Uint(UintTy), - Float(FloatTy), -} - -/// Whether a function is safe or not. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Safety { - /// Safe - Safe, - /// Unsafe - Unsafe, -} - -/// Whether a type is mutable or not. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Mutability { - /// Mutable - Mut, - /// Immutable - Not, -} - -/// An universe index is how a universally quantified parameter is -/// represented when it's binder is moved into the environment. -/// An example chain of transformations would be: -/// `forall<T> { Goal(T) }` (syntactical representation) -/// `forall { Goal(?0) }` (used a DeBruijn index) -/// `Goal(!U1)` (the quantifier was moved to the environment and replaced with a universe index) -/// See <https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes> for more. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct UniverseIndex { - /// The counter for the universe index, starts with 0. - pub counter: usize, -} - -impl UniverseIndex { - /// Root universe index (0). - pub const ROOT: UniverseIndex = UniverseIndex { counter: 0 }; - - /// Root universe index (0). - pub fn root() -> UniverseIndex { - Self::ROOT - } - - /// Whether one universe can "see" another. - pub fn can_see(self, ui: UniverseIndex) -> bool { - self.counter >= ui.counter - } - - /// Increases the index counter. - pub fn next(self) -> UniverseIndex { - UniverseIndex { - counter: self.counter + 1, - } - } -} - -/// Maps the universes found in the `u_canonicalize` result (the -/// "canonical" universes) to the universes found in the original -/// value (and vice versa). When used as a folder -- i.e., from -/// outside this module -- converts from "canonical" universes to the -/// original (but see the `UMapToCanonical` folder). -#[derive(Clone, Debug)] -pub struct UniverseMap { - /// A reverse map -- for each universe Ux that appears in - /// `quantified`, the corresponding universe in the original was - /// `universes[x]`. - pub universes: Vec<UniverseIndex>, -} - -impl UniverseMap { - /// Creates a new universe map. - pub fn new() -> Self { - UniverseMap { - universes: vec![UniverseIndex::root()], - } - } - - /// Number of canonical universes. - pub fn num_canonical_universes(&self) -> usize { - self.universes.len() - } -} - -/// The id for an Abstract Data Type (i.e. structs, unions and enums). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct AdtId<I: Interner>(pub I::InternedAdtId); - -/// The id of a trait definition; could be used to load the trait datum by -/// invoking the [`trait_datum`] method. -/// -/// [`trait_datum`]: ../chalk_solve/trait.RustIrDatabase.html#tymethod.trait_datum -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct TraitId<I: Interner>(pub I::DefId); - -/// The id for an impl. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ImplId<I: Interner>(pub I::DefId); - -/// Id for a specific clause. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ClauseId<I: Interner>(pub I::DefId); - -/// The id for the associated type member of a trait. The details of the type -/// can be found by invoking the [`associated_ty_data`] method. -/// -/// [`associated_ty_data`]: ../chalk_solve/trait.RustIrDatabase.html#tymethod.associated_ty_data -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct AssocTypeId<I: Interner>(pub I::DefId); - -/// Id for an opaque type. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct OpaqueTyId<I: Interner>(pub I::DefId); - -/// Function definition id. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct FnDefId<I: Interner>(pub I::DefId); - -/// Id for Rust closures. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ClosureId<I: Interner>(pub I::DefId); - -/// Id for Rust generators. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct GeneratorId<I: Interner>(pub I::DefId); - -/// Id for foreign types. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ForeignDefId<I: Interner>(pub I::DefId); - -impl_debugs!(ImplId, ClauseId); - -/// A Rust type. The actual type data is stored in `TyKind`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct Ty<I: Interner> { - interned: I::InternedType, -} - -impl<I: Interner> Ty<I> { - /// Creates a type from `TyKind`. - pub fn new(interner: I, data: impl CastTo<TyKind<I>>) -> Self { - let ty_kind = data.cast(interner); - Ty { - interned: I::intern_ty(interner, ty_kind), - } - } - - /// Gets the interned type. - pub fn interned(&self) -> &I::InternedType { - &self.interned - } - - /// Gets the underlying type data. - pub fn data(&self, interner: I) -> &TyData<I> { - I::ty_data(interner, &self.interned) - } - - /// Gets the underlying type kind. - pub fn kind(&self, interner: I) -> &TyKind<I> { - &I::ty_data(interner, &self.interned).kind - } - - /// Creates a `FromEnv` constraint using this type. - pub fn from_env(&self) -> FromEnv<I> { - FromEnv::Ty(self.clone()) - } - - /// Creates a WF-constraint for this type. - pub fn well_formed(&self) -> WellFormed<I> { - WellFormed::Ty(self.clone()) - } - - /// Creates a domain goal `FromEnv(T)` where `T` is this type. - pub fn into_from_env_goal(self, interner: I) -> DomainGoal<I> { - self.from_env().cast(interner) - } - - /// If this is a `TyKind::BoundVar(d)`, returns `Some(d)` else `None`. - pub fn bound_var(&self, interner: I) -> Option<BoundVar> { - if let TyKind::BoundVar(bv) = self.kind(interner) { - Some(*bv) - } else { - None - } - } - - /// If this is a `TyKind::InferenceVar(d)`, returns `Some(d)` else `None`. - pub fn inference_var(&self, interner: I) -> Option<InferenceVar> { - if let TyKind::InferenceVar(depth, _) = self.kind(interner) { - Some(*depth) - } else { - None - } - } - - /// Returns true if this is a `BoundVar` or an `InferenceVar` of `TyVariableKind::General`. - pub fn is_general_var(&self, interner: I, binders: &CanonicalVarKinds<I>) -> bool { - match self.kind(interner) { - TyKind::BoundVar(bv) - if bv.debruijn == DebruijnIndex::INNERMOST - && binders.at(interner, bv.index).kind - == VariableKind::Ty(TyVariableKind::General) => - { - true - } - TyKind::InferenceVar(_, TyVariableKind::General) => true, - _ => false, - } - } - - /// Returns true if this is an `Alias`. - pub fn is_alias(&self, interner: I) -> bool { - matches!(self.kind(interner), TyKind::Alias(..)) - } - - /// Returns true if this is an `IntTy` or `UintTy`. - pub fn is_integer(&self, interner: I) -> bool { - matches!( - self.kind(interner), - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) - ) - } - - /// Returns true if this is a `FloatTy`. - pub fn is_float(&self, interner: I) -> bool { - matches!(self.kind(interner), TyKind::Scalar(Scalar::Float(_))) - } - - /// Returns `Some(adt_id)` if this is an ADT, `None` otherwise - pub fn adt_id(&self, interner: I) -> Option<AdtId<I>> { - match self.kind(interner) { - TyKind::Adt(adt_id, _) => Some(*adt_id), - _ => None, - } - } - - /// True if this type contains "bound" types/lifetimes, and hence - /// needs to be shifted across binders. This is a very inefficient - /// check, intended only for debug assertions, because I am lazy. - pub fn needs_shift(&self, interner: I) -> bool { - self.has_free_vars(interner) - } -} - -/// Contains the data for a Ty -#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -pub struct TyData<I: Interner> { - /// The kind - pub kind: TyKind<I>, - /// Type flags - pub flags: TypeFlags, -} - -bitflags! { - /// Contains flags indicating various properties of a Ty - pub struct TypeFlags : u16 { - /// Does the type contain an InferenceVar - const HAS_TY_INFER = 1; - /// Does the type contain a lifetime with an InferenceVar - const HAS_RE_INFER = 1 << 1; - /// Does the type contain a ConstValue with an InferenceVar - const HAS_CT_INFER = 1 << 2; - /// Does the type contain a Placeholder TyKind - const HAS_TY_PLACEHOLDER = 1 << 3; - /// Does the type contain a lifetime with a Placeholder - const HAS_RE_PLACEHOLDER = 1 << 4; - /// Does the type contain a ConstValue Placeholder - const HAS_CT_PLACEHOLDER = 1 << 5; - /// True when the type has free lifetimes related to a local context - const HAS_FREE_LOCAL_REGIONS = 1 << 6; - /// Does the type contain a projection of an associated type - const HAS_TY_PROJECTION = 1 << 7; - /// Does the type contain an opaque type - const HAS_TY_OPAQUE = 1 << 8; - /// Does the type contain an unevaluated const projection - const HAS_CT_PROJECTION = 1 << 9; - /// Does the type contain an error - const HAS_ERROR = 1 << 10; - /// Does the type contain any free lifetimes - const HAS_FREE_REGIONS = 1 << 11; - /// True when the type contains lifetimes that will be substituted when function is called - const HAS_RE_LATE_BOUND = 1 << 12; - /// True when the type contains an erased lifetime - const HAS_RE_ERASED = 1 << 13; - /// Does the type contain placeholders or inference variables that could be replaced later - const STILL_FURTHER_SPECIALIZABLE = 1 << 14; - - /// True when the type contains free names local to a particular context - const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_CT_INFER.bits - | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits - | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; - - /// Does the type contain any form of projection - const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits - | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_CT_PROJECTION.bits; - } -} -/// Type data, which holds the actual type information. -#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -pub enum TyKind<I: Interner> { - /// Abstract data types, i.e., structs, unions, or enumerations. - /// For example, a type like `Vec<T>`. - Adt(AdtId<I>, Substitution<I>), - - /// an associated type like `Iterator::Item`; see `AssociatedType` for details - AssociatedType(AssocTypeId<I>, Substitution<I>), - - /// a scalar type like `bool` or `u32` - Scalar(Scalar), - - /// a tuple of the given arity - Tuple(usize, Substitution<I>), - - /// an array type like `[T; N]` - Array(Ty<I>, Const<I>), - - /// a slice type like `[T]` - Slice(Ty<I>), - - /// a raw pointer type like `*const T` or `*mut T` - Raw(Mutability, Ty<I>), - - /// a reference type like `&T` or `&mut T` - Ref(Mutability, Lifetime<I>, Ty<I>), - - /// a placeholder for opaque types like `impl Trait` - OpaqueType(OpaqueTyId<I>, Substitution<I>), - - /// a function definition - FnDef(FnDefId<I>, Substitution<I>), - - /// the string primitive type - Str, - - /// the never type `!` - Never, - - /// A closure. - Closure(ClosureId<I>, Substitution<I>), - - /// A generator. - Generator(GeneratorId<I>, Substitution<I>), - - /// A generator witness. - GeneratorWitness(GeneratorId<I>, Substitution<I>), - - /// foreign types - Foreign(ForeignDefId<I>), - - /// This can be used to represent an error, e.g. during name resolution of a type. - /// Chalk itself will not produce this, just pass it through when given. - Error, - - /// instantiated from a universally quantified type, e.g., from - /// `forall<T> { .. }`. Stands in as a representative of "some - /// unknown type". - Placeholder(PlaceholderIndex), - - /// A "dyn" type is a trait object type created via the "dyn Trait" syntax. - /// In the chalk parser, the traits that the object represents is parsed as - /// a QuantifiedInlineBound, and is then changed to a list of where clauses - /// during lowering. - /// - /// See the `Opaque` variant for a discussion about the use of - /// binders here. - Dyn(DynTy<I>), - - /// An "alias" type represents some form of type alias, such as: - /// - An associated type projection like `<T as Iterator>::Item` - /// - `impl Trait` types - /// - Named type aliases like `type Foo<X> = Vec<X>` - Alias(AliasTy<I>), - - /// A function type such as `for<'a> fn(&'a u32)`. - /// Note that "higher-ranked" types (starting with `for<>`) are either - /// function types or dyn types, and do not appear otherwise in Rust - /// surface syntax. - Function(FnPointer<I>), - - /// References the binding at the given depth. The index is a [de - /// Bruijn index], so it counts back through the in-scope binders. - BoundVar(BoundVar), - - /// Inference variable defined in the current inference context. - InferenceVar(InferenceVar, TyVariableKind), -} - -impl<I: Interner> Copy for TyKind<I> -where - I::InternedLifetime: Copy, - I::InternedSubstitution: Copy, - I::InternedVariableKinds: Copy, - I::InternedQuantifiedWhereClauses: Copy, - I::InternedType: Copy, - I::InternedConst: Copy, -{ -} - -impl<I: Interner> TyKind<I> { - /// Casts the type data to a type. - pub fn intern(self, interner: I) -> Ty<I> { - Ty::new(interner, self) - } - - /// Compute type flags for a TyKind - pub fn compute_flags(&self, interner: I) -> TypeFlags { - match self { - TyKind::Adt(_, substitution) - | TyKind::AssociatedType(_, substitution) - | TyKind::Tuple(_, substitution) - | TyKind::Closure(_, substitution) - | TyKind::Generator(_, substitution) - | TyKind::GeneratorWitness(_, substitution) - | TyKind::FnDef(_, substitution) - | TyKind::OpaqueType(_, substitution) => substitution.compute_flags(interner), - TyKind::Scalar(_) | TyKind::Str | TyKind::Never | TyKind::Foreign(_) => { - TypeFlags::empty() - } - TyKind::Error => TypeFlags::HAS_ERROR, - TyKind::Slice(ty) | TyKind::Raw(_, ty) => ty.data(interner).flags, - TyKind::Ref(_, lifetime, ty) => { - lifetime.compute_flags(interner) | ty.data(interner).flags - } - TyKind::Array(ty, const_ty) => { - let flags = ty.data(interner).flags; - let const_data = const_ty.data(interner); - flags - | const_data.ty.data(interner).flags - | match const_data.value { - ConstValue::BoundVar(_) | ConstValue::Concrete(_) => TypeFlags::empty(), - ConstValue::InferenceVar(_) => { - TypeFlags::HAS_CT_INFER | TypeFlags::STILL_FURTHER_SPECIALIZABLE - } - ConstValue::Placeholder(_) => { - TypeFlags::HAS_CT_PLACEHOLDER | TypeFlags::STILL_FURTHER_SPECIALIZABLE - } - } - } - TyKind::Placeholder(_) => TypeFlags::HAS_TY_PLACEHOLDER, - TyKind::Dyn(dyn_ty) => { - let lifetime_flags = dyn_ty.lifetime.compute_flags(interner); - let mut dyn_flags = TypeFlags::empty(); - for var_kind in dyn_ty.bounds.skip_binders().iter(interner) { - match &(var_kind.skip_binders()) { - WhereClause::Implemented(trait_ref) => { - dyn_flags |= trait_ref.substitution.compute_flags(interner) - } - WhereClause::AliasEq(alias_eq) => { - dyn_flags |= alias_eq.alias.compute_flags(interner); - dyn_flags |= alias_eq.ty.data(interner).flags; - } - WhereClause::LifetimeOutlives(lifetime_outlives) => { - dyn_flags |= lifetime_outlives.a.compute_flags(interner) - | lifetime_outlives.b.compute_flags(interner); - } - WhereClause::TypeOutlives(type_outlives) => { - dyn_flags |= type_outlives.ty.data(interner).flags; - dyn_flags |= type_outlives.lifetime.compute_flags(interner); - } - } - } - lifetime_flags | dyn_flags - } - TyKind::Alias(alias_ty) => alias_ty.compute_flags(interner), - TyKind::BoundVar(_) => TypeFlags::empty(), - TyKind::InferenceVar(_, _) => TypeFlags::HAS_TY_INFER, - TyKind::Function(fn_pointer) => fn_pointer.substitution.0.compute_flags(interner), - } - } -} - -/// Identifies a particular bound variable within a binder. -/// Variables are identified by the combination of a [`DebruijnIndex`], -/// which identifies the *binder*, and an index within that binder. -/// -/// Consider this case: -/// -/// ```ignore -/// forall<'a, 'b> { forall<'c, 'd> { ... } } -/// ``` -/// -/// Within the `...` term: -/// -/// * the variable `'a` have a debruijn index of 1 and index 0 -/// * the variable `'b` have a debruijn index of 1 and index 1 -/// * the variable `'c` have a debruijn index of 0 and index 0 -/// * the variable `'d` have a debruijn index of 0 and index 1 -/// -/// The variables `'a` and `'b` both have debruijn index of 1 because, -/// counting out, they are the 2nd binder enclosing `...`. The indices -/// identify the location *within* that binder. -/// -/// The variables `'c` and `'d` both have debruijn index of 0 because -/// they appear in the *innermost* binder enclosing the `...`. The -/// indices identify the location *within* that binder. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct BoundVar { - /// Debruijn index, which identifies the binder. - pub debruijn: DebruijnIndex, - /// Index within the binder. - pub index: usize, -} - -impl BoundVar { - /// Creates a new bound variable. - pub fn new(debruijn: DebruijnIndex, index: usize) -> Self { - Self { debruijn, index } - } - - /// Casts the bound variable to a type. - pub fn to_ty<I: Interner>(self, interner: I) -> Ty<I> { - TyKind::<I>::BoundVar(self).intern(interner) - } - - /// Wrap the bound variable in a lifetime. - pub fn to_lifetime<I: Interner>(self, interner: I) -> Lifetime<I> { - LifetimeData::<I>::BoundVar(self).intern(interner) - } - - /// Wraps the bound variable in a constant. - pub fn to_const<I: Interner>(self, interner: I, ty: Ty<I>) -> Const<I> { - ConstData { - ty, - value: ConstValue::<I>::BoundVar(self), - } - .intern(interner) - } - - /// True if this variable is bound within the `amount` innermost binders. - pub fn bound_within(self, outer_binder: DebruijnIndex) -> bool { - self.debruijn.within(outer_binder) - } - - /// Adjusts the debruijn index (see [`DebruijnIndex::shifted_in`]). - #[must_use] - pub fn shifted_in(self) -> Self { - BoundVar::new(self.debruijn.shifted_in(), self.index) - } - - /// Adjusts the debruijn index (see [`DebruijnIndex::shifted_in`]). - #[must_use] - pub fn shifted_in_from(self, outer_binder: DebruijnIndex) -> Self { - BoundVar::new(self.debruijn.shifted_in_from(outer_binder), self.index) - } - - /// Adjusts the debruijn index (see [`DebruijnIndex::shifted_in`]). - #[must_use] - pub fn shifted_out(self) -> Option<Self> { - self.debruijn - .shifted_out() - .map(|db| BoundVar::new(db, self.index)) - } - - /// Adjusts the debruijn index (see [`DebruijnIndex::shifted_in`]). - #[must_use] - pub fn shifted_out_to(self, outer_binder: DebruijnIndex) -> Option<Self> { - self.debruijn - .shifted_out_to(outer_binder) - .map(|db| BoundVar::new(db, self.index)) - } - - /// Return the index of the bound variable, but only if it is bound - /// at the innermost binder. Otherwise, returns `None`. - pub fn index_if_innermost(self) -> Option<usize> { - self.index_if_bound_at(DebruijnIndex::INNERMOST) - } - - /// Return the index of the bound variable, but only if it is bound - /// at the innermost binder. Otherwise, returns `None`. - pub fn index_if_bound_at(self, debruijn: DebruijnIndex) -> Option<usize> { - if self.debruijn == debruijn { - Some(self.index) - } else { - None - } - } -} - -/// References the binder at the given depth. The index is a [de -/// Bruijn index], so it counts back through the in-scope binders, -/// with 0 being the innermost binder. This is used in impls and -/// the like. For example, if we had a rule like `for<T> { (T: -/// Clone) :- (T: Copy) }`, then `T` would be represented as a -/// `BoundVar(0)` (as the `for` is the innermost binder). -/// -/// [de Bruijn index]: https://en.wikipedia.org/wiki/De_Bruijn_index -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct DebruijnIndex { - depth: u32, -} - -impl DebruijnIndex { - /// Innermost index. - pub const INNERMOST: DebruijnIndex = DebruijnIndex { depth: 0 }; - /// One level higher than the innermost index. - pub const ONE: DebruijnIndex = DebruijnIndex { depth: 1 }; - - /// Creates a new de Bruijn index with a given depth. - pub fn new(depth: u32) -> Self { - DebruijnIndex { depth } - } - - /// Depth of the De Bruijn index, counting from 0 starting with - /// the innermost binder. - pub fn depth(self) -> u32 { - self.depth - } - - /// True if the binder identified by this index is within the - /// binder identified by the index `outer_binder`. - /// - /// # Example - /// - /// Imagine you have the following binders in scope - /// - /// ```ignore - /// forall<a> forall<b> forall<c> - /// ``` - /// - /// then the Debruijn index for `c` would be `0`, the index for - /// `b` would be 1, and so on. Now consider the following calls: - /// - /// * `c.within(a) = true` - /// * `b.within(a) = true` - /// * `a.within(a) = false` - /// * `a.within(c) = false` - pub fn within(self, outer_binder: DebruijnIndex) -> bool { - self < outer_binder - } - - /// Returns the resulting index when this value is moved into - /// through one binder. - #[must_use] - pub fn shifted_in(self) -> DebruijnIndex { - self.shifted_in_from(DebruijnIndex::ONE) - } - - /// Update this index in place by shifting it "in" through - /// `amount` number of binders. - pub fn shift_in(&mut self) { - *self = self.shifted_in(); - } - - /// Adds `outer_binder` levels to the `self` index. Intuitively, this - /// shifts the `self` index, which was valid at the outer binder, - /// so that it is valid at the innermost binder. - /// - /// Example: Assume that the following binders are in scope: - /// - /// ```ignore - /// for<A> for<B> for<C> for<D> - /// ^ outer binder - /// ``` - /// - /// Assume further that the `outer_binder` argument is 2, - /// which means that it is referring to the `for<B>` binder - /// (since `D` would be the innermost binder). - /// - /// This means that `self` is relative to the binder `B` -- so - /// if `self` is 0 (`INNERMOST`), then it refers to `B`, - /// and if `self` is 1, then it refers to `A`. - /// - /// We will return as follows: - /// - /// * `0.shifted_in_from(2) = 2` -- i.e., `B`, when shifted in to the binding level `D`, has index 2 - /// * `1.shifted_in_from(2) = 3` -- i.e., `A`, when shifted in to the binding level `D`, has index 3 - /// * `2.shifted_in_from(1) = 3` -- here, we changed the `outer_binder` to refer to `C`. - /// Therefore `2` (relative to `C`) refers to `A`, so the result is still 3 (since `A`, relative to the - /// innermost binder, has index 3). - #[must_use] - pub fn shifted_in_from(self, outer_binder: DebruijnIndex) -> DebruijnIndex { - DebruijnIndex::new(self.depth() + outer_binder.depth()) - } - - /// Returns the resulting index when this value is moved out from - /// `amount` number of new binders. - #[must_use] - pub fn shifted_out(self) -> Option<DebruijnIndex> { - self.shifted_out_to(DebruijnIndex::ONE) - } - - /// Update in place by shifting out from `amount` binders. - pub fn shift_out(&mut self) { - *self = self.shifted_out().unwrap(); - } - - /// Subtracts `outer_binder` levels from the `self` index. Intuitively, this - /// shifts the `self` index, which was valid at the innermost - /// binder, to one that is valid at the binder `outer_binder`. - /// - /// This will return `None` if the `self` index is internal to the - /// outer binder (i.e., if `self < outer_binder`). - /// - /// Example: Assume that the following binders are in scope: - /// - /// ```ignore - /// for<A> for<B> for<C> for<D> - /// ^ outer binder - /// ``` - /// - /// Assume further that the `outer_binder` argument is 2, - /// which means that it is referring to the `for<B>` binder - /// (since `D` would be the innermost binder). - /// - /// This means that the result is relative to the binder `B` -- so - /// if `self` is 0 (`INNERMOST`), then it refers to `B`, - /// and if `self` is 1, then it refers to `A`. - /// - /// We will return as follows: - /// - /// * `1.shifted_out_to(2) = None` -- i.e., the binder for `C` can't be named from the binding level `B` - /// * `3.shifted_out_to(2) = Some(1)` -- i.e., `A`, when shifted out to the binding level `B`, has index 1 - pub fn shifted_out_to(self, outer_binder: DebruijnIndex) -> Option<DebruijnIndex> { - if self.within(outer_binder) { - None - } else { - Some(DebruijnIndex::new(self.depth() - outer_binder.depth())) - } - } -} - -/// A "DynTy" represents a trait object (`dyn Trait`). Trait objects -/// are conceptually very related to an "existential type" of the form -/// `exists<T> { T: Trait }` (another example of such type is `impl Trait`). -/// `DynTy` represents the bounds on that type. -/// -/// The "bounds" here represents the unknown self type. So, a type like -/// `dyn for<'a> Fn(&'a u32)` would be represented with two-levels of -/// binder, as "depicted" here: -/// -/// ```notrust -/// exists<type> { -/// vec![ -/// // A QuantifiedWhereClause: -/// forall<region> { ^1.0: Fn(&^0.0 u32) } -/// ] -/// } -/// ``` -/// -/// The outer `exists<type>` binder indicates that there exists -/// some type that meets the criteria within, but that type is not -/// known. It is referenced within the type using `^1.0`, indicating -/// a bound type with debruijn index 1 (i.e., skipping through one -/// level of binder). -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct DynTy<I: Interner> { - /// The unknown self type. - pub bounds: Binders<QuantifiedWhereClauses<I>>, - /// Lifetime of the `DynTy`. - pub lifetime: Lifetime<I>, -} - -impl<I: Interner> Copy for DynTy<I> -where - I::InternedLifetime: Copy, - I::InternedQuantifiedWhereClauses: Copy, - I::InternedVariableKinds: Copy, -{ -} - -/// A type, lifetime or constant whose value is being inferred. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct InferenceVar { - index: u32, -} - -impl From<u32> for InferenceVar { - fn from(index: u32) -> InferenceVar { - InferenceVar { index } - } -} - -impl InferenceVar { - /// Gets the underlying index value. - pub fn index(self) -> u32 { - self.index - } - - /// Wraps the inference variable in a type. - pub fn to_ty<I: Interner>(self, interner: I, kind: TyVariableKind) -> Ty<I> { - TyKind::<I>::InferenceVar(self, kind).intern(interner) - } - - /// Wraps the inference variable in a lifetime. - pub fn to_lifetime<I: Interner>(self, interner: I) -> Lifetime<I> { - LifetimeData::<I>::InferenceVar(self).intern(interner) - } - - /// Wraps the inference variable in a constant. - pub fn to_const<I: Interner>(self, interner: I, ty: Ty<I>) -> Const<I> { - ConstData { - ty, - value: ConstValue::<I>::InferenceVar(self), - } - .intern(interner) - } -} - -/// A function signature. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HasInterner, Debug)] -#[allow(missing_docs)] -pub struct FnSig<I: Interner> { - pub abi: I::FnAbi, - pub safety: Safety, - pub variadic: bool, -} -/// A wrapper for the substs on a Fn. -#[derive(Clone, PartialEq, Eq, Hash, HasInterner, Fold, Visit)] -pub struct FnSubst<I: Interner>(pub Substitution<I>); - -impl<I: Interner> Copy for FnSubst<I> where I::InternedSubstitution: Copy {} - -/// for<'a...'z> X -- all binders are instantiated at once, -/// and we use deBruijn indices within `self.ty` -#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -#[allow(missing_docs)] -pub struct FnPointer<I: Interner> { - pub num_binders: usize, - pub sig: FnSig<I>, - pub substitution: FnSubst<I>, -} - -impl<I: Interner> Copy for FnPointer<I> where I::InternedSubstitution: Copy {} - -impl<I: Interner> FnPointer<I> { - /// Represent the current `Fn` as if it was wrapped in `Binders` - pub fn into_binders(self, interner: I) -> Binders<FnSubst<I>> { - Binders::new( - VariableKinds::from_iter( - interner, - (0..self.num_binders).map(|_| VariableKind::Lifetime), - ), - self.substitution, - ) - } - - /// Represent the current `Fn` as if it was wrapped in `Binders` - pub fn as_binders(&self, interner: I) -> Binders<&FnSubst<I>> { - Binders::new( - VariableKinds::from_iter( - interner, - (0..self.num_binders).map(|_| VariableKind::Lifetime), - ), - &self.substitution, - ) - } -} - -/// Constants. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct Const<I: Interner> { - interned: I::InternedConst, -} - -impl<I: Interner> Const<I> { - /// Create a `Const` using something that can be cast to const data. - pub fn new(interner: I, data: impl CastTo<ConstData<I>>) -> Self { - Const { - interned: I::intern_const(interner, data.cast(interner)), - } - } - - /// Gets the interned constant. - pub fn interned(&self) -> &I::InternedConst { - &self.interned - } - - /// Gets the constant data from the interner. - pub fn data(&self, interner: I) -> &ConstData<I> { - I::const_data(interner, &self.interned) - } - - /// If this is a `ConstData::BoundVar(d)`, returns `Some(d)` else `None`. - pub fn bound_var(&self, interner: I) -> Option<BoundVar> { - if let ConstValue::BoundVar(bv) = &self.data(interner).value { - Some(*bv) - } else { - None - } - } - - /// If this is a `ConstData::InferenceVar(d)`, returns `Some(d)` else `None`. - pub fn inference_var(&self, interner: I) -> Option<InferenceVar> { - if let ConstValue::InferenceVar(iv) = &self.data(interner).value { - Some(*iv) - } else { - None - } - } - - /// True if this const is a "bound" const, and hence - /// needs to be shifted across binders. Meant for debug assertions. - pub fn needs_shift(&self, interner: I) -> bool { - match &self.data(interner).value { - ConstValue::BoundVar(_) => true, - ConstValue::InferenceVar(_) => false, - ConstValue::Placeholder(_) => false, - ConstValue::Concrete(_) => false, - } - } -} - -/// Constant data, containing the constant's type and value. -#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -pub struct ConstData<I: Interner> { - /// Type that holds the constant. - pub ty: Ty<I>, - /// The value of the constant. - pub value: ConstValue<I>, -} - -/// A constant value, not necessarily concrete. -#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -pub enum ConstValue<I: Interner> { - /// Bound var (e.g. a parameter). - BoundVar(BoundVar), - /// Constant whose value is being inferred. - InferenceVar(InferenceVar), - /// Lifetime on some yet-unknown placeholder. - Placeholder(PlaceholderIndex), - /// Concrete constant value. - Concrete(ConcreteConst<I>), -} - -impl<I: Interner> Copy for ConstValue<I> where I::InternedConcreteConst: Copy {} - -impl<I: Interner> ConstData<I> { - /// Wraps the constant data in a `Const`. - pub fn intern(self, interner: I) -> Const<I> { - Const::new(interner, self) - } -} - -/// Concrete constant, whose value is known (as opposed to -/// inferred constants and placeholders). -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct ConcreteConst<I: Interner> { - /// The interned constant. - pub interned: I::InternedConcreteConst, -} - -impl<I: Interner> ConcreteConst<I> { - /// Checks whether two concrete constants are equal. - pub fn const_eq(&self, ty: &Ty<I>, other: &ConcreteConst<I>, interner: I) -> bool { - interner.const_eq(&ty.interned, &self.interned, &other.interned) - } -} - -/// A Rust lifetime. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct Lifetime<I: Interner> { - interned: I::InternedLifetime, -} - -impl<I: Interner> Lifetime<I> { - /// Create a lifetime from lifetime data - /// (or something that can be cast to lifetime data). - pub fn new(interner: I, data: impl CastTo<LifetimeData<I>>) -> Self { - Lifetime { - interned: I::intern_lifetime(interner, data.cast(interner)), - } - } - - /// Gets the interned value. - pub fn interned(&self) -> &I::InternedLifetime { - &self.interned - } - - /// Gets the lifetime data. - pub fn data(&self, interner: I) -> &LifetimeData<I> { - I::lifetime_data(interner, &self.interned) - } - - /// If this is a `Lifetime::BoundVar(d)`, returns `Some(d)` else `None`. - pub fn bound_var(&self, interner: I) -> Option<BoundVar> { - if let LifetimeData::BoundVar(bv) = self.data(interner) { - Some(*bv) - } else { - None - } - } - - /// If this is a `Lifetime::InferenceVar(d)`, returns `Some(d)` else `None`. - pub fn inference_var(&self, interner: I) -> Option<InferenceVar> { - if let LifetimeData::InferenceVar(depth) = self.data(interner) { - Some(*depth) - } else { - None - } - } - - /// True if this lifetime is a "bound" lifetime, and hence - /// needs to be shifted across binders. Meant for debug assertions. - pub fn needs_shift(&self, interner: I) -> bool { - match self.data(interner) { - LifetimeData::BoundVar(_) => true, - LifetimeData::InferenceVar(_) => false, - LifetimeData::Placeholder(_) => false, - LifetimeData::Static => false, - LifetimeData::Empty(_) => false, - LifetimeData::Erased => false, - LifetimeData::Phantom(..) => unreachable!(), - } - } - - ///compute type flags for Lifetime - fn compute_flags(&self, interner: I) -> TypeFlags { - match self.data(interner) { - LifetimeData::InferenceVar(_) => { - TypeFlags::HAS_RE_INFER - | TypeFlags::HAS_FREE_LOCAL_REGIONS - | TypeFlags::HAS_FREE_REGIONS - } - LifetimeData::Placeholder(_) => { - TypeFlags::HAS_RE_PLACEHOLDER - | TypeFlags::HAS_FREE_LOCAL_REGIONS - | TypeFlags::HAS_FREE_REGIONS - } - LifetimeData::Static | LifetimeData::Empty(_) => TypeFlags::HAS_FREE_REGIONS, - LifetimeData::Phantom(_, _) => TypeFlags::empty(), - LifetimeData::BoundVar(_) => TypeFlags::HAS_RE_LATE_BOUND, - LifetimeData::Erased => TypeFlags::HAS_RE_ERASED, - } - } -} - -/// Lifetime data, including what kind of lifetime it is and what it points to. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub enum LifetimeData<I: Interner> { - /// See TyKind::BoundVar. - BoundVar(BoundVar), - /// Lifetime whose value is being inferred. - InferenceVar(InferenceVar), - /// Lifetime on some yet-unknown placeholder. - Placeholder(PlaceholderIndex), - /// Static lifetime - Static, - /// An empty lifetime: a lifetime shorter than any other lifetime in a - /// universe with a lesser or equal index. The universe only non-zero in - /// lexical region resolve in rustc, so chalk shouldn't ever see a non-zero - /// index. - Empty(UniverseIndex), - /// An erased lifetime, used by rustc to improve caching when we doesn't - /// care about lifetimes - Erased, - /// Lifetime on phantom data. - Phantom(Void, PhantomData<I>), -} - -impl<I: Interner> LifetimeData<I> { - /// Wrap the lifetime data in a lifetime. - pub fn intern(self, interner: I) -> Lifetime<I> { - Lifetime::new(interner, self) - } -} - -/// Index of an universally quantified parameter in the environment. -/// Two indexes are required, the one of the universe itself -/// and the relative index inside the universe. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct PlaceholderIndex { - /// Index *of* the universe. - pub ui: UniverseIndex, - /// Index *in* the universe. - pub idx: usize, -} - -impl PlaceholderIndex { - /// Wrap the placeholder instance in a lifetime. - pub fn to_lifetime<I: Interner>(self, interner: I) -> Lifetime<I> { - LifetimeData::<I>::Placeholder(self).intern(interner) - } - - /// Create an interned type. - pub fn to_ty<I: Interner>(self, interner: I) -> Ty<I> { - TyKind::Placeholder(self).intern(interner) - } - - /// Wrap the placeholder index in a constant. - pub fn to_const<I: Interner>(self, interner: I, ty: Ty<I>) -> Const<I> { - ConstData { - ty, - value: ConstValue::Placeholder(self), - } - .intern(interner) - } -} -/// Represents some extra knowledge we may have about the type variable. -/// ```ignore -/// let x: &[u32]; -/// let i = 1; -/// x[i] -/// ``` -/// In this example, `i` is known to be some type of integer. We can infer that -/// it is `usize` because that is the only integer type that slices have an -/// `Index` impl for. `i` would have a `TyVariableKind` of `Integer` to guide the -/// inference process. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[allow(missing_docs)] -pub enum TyVariableKind { - General, - Integer, - Float, -} - -/// The "kind" of variable. Type, lifetime or constant. -#[derive(Clone, PartialEq, Eq, Hash)] -#[allow(missing_docs)] -pub enum VariableKind<I: Interner> { - Ty(TyVariableKind), - Lifetime, - Const(Ty<I>), -} - -impl<I: Interner> interner::HasInterner for VariableKind<I> { - type Interner = I; -} - -impl<I: Interner> Copy for VariableKind<I> where I::InternedType: Copy {} - -impl<I: Interner> VariableKind<I> { - fn to_bound_variable(&self, interner: I, bound_var: BoundVar) -> GenericArg<I> { - match self { - VariableKind::Ty(_) => { - GenericArgData::Ty(TyKind::BoundVar(bound_var).intern(interner)).intern(interner) - } - VariableKind::Lifetime => { - GenericArgData::Lifetime(LifetimeData::BoundVar(bound_var).intern(interner)) - .intern(interner) - } - VariableKind::Const(ty) => GenericArgData::Const( - ConstData { - ty: ty.clone(), - value: ConstValue::BoundVar(bound_var), - } - .intern(interner), - ) - .intern(interner), - } - } -} - -/// A generic argument, see `GenericArgData` for more information. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct GenericArg<I: Interner> { - interned: I::InternedGenericArg, -} - -impl<I: Interner> GenericArg<I> { - /// Constructs a generic argument using `GenericArgData`. - pub fn new(interner: I, data: GenericArgData<I>) -> Self { - let interned = I::intern_generic_arg(interner, data); - GenericArg { interned } - } - - /// Gets the interned value. - pub fn interned(&self) -> &I::InternedGenericArg { - &self.interned - } - - /// Gets the underlying data. - pub fn data(&self, interner: I) -> &GenericArgData<I> { - I::generic_arg_data(interner, &self.interned) - } - - /// Asserts that this is a type argument. - pub fn assert_ty_ref(&self, interner: I) -> &Ty<I> { - self.ty(interner).unwrap() - } - - /// Asserts that this is a lifetime argument. - pub fn assert_lifetime_ref(&self, interner: I) -> &Lifetime<I> { - self.lifetime(interner).unwrap() - } - - /// Asserts that this is a constant argument. - pub fn assert_const_ref(&self, interner: I) -> &Const<I> { - self.constant(interner).unwrap() - } - - /// Checks whether the generic argument is a type. - pub fn is_ty(&self, interner: I) -> bool { - match self.data(interner) { - GenericArgData::Ty(_) => true, - GenericArgData::Lifetime(_) => false, - GenericArgData::Const(_) => false, - } - } - - /// Returns the type if it is one, `None` otherwise. - pub fn ty(&self, interner: I) -> Option<&Ty<I>> { - match self.data(interner) { - GenericArgData::Ty(t) => Some(t), - _ => None, - } - } - - /// Returns the lifetime if it is one, `None` otherwise. - pub fn lifetime(&self, interner: I) -> Option<&Lifetime<I>> { - match self.data(interner) { - GenericArgData::Lifetime(t) => Some(t), - _ => None, - } - } - - /// Returns the constant if it is one, `None` otherwise. - pub fn constant(&self, interner: I) -> Option<&Const<I>> { - match self.data(interner) { - GenericArgData::Const(c) => Some(c), - _ => None, - } - } - - /// Compute type flags for GenericArg<I> - fn compute_flags(&self, interner: I) -> TypeFlags { - match self.data(interner) { - GenericArgData::Ty(ty) => ty.data(interner).flags, - GenericArgData::Lifetime(lifetime) => lifetime.compute_flags(interner), - GenericArgData::Const(constant) => { - let data = constant.data(interner); - let flags = data.ty.data(interner).flags; - match data.value { - ConstValue::BoundVar(_) => flags, - ConstValue::InferenceVar(_) => { - flags | TypeFlags::HAS_CT_INFER | TypeFlags::STILL_FURTHER_SPECIALIZABLE - } - ConstValue::Placeholder(_) => { - flags - | TypeFlags::HAS_CT_PLACEHOLDER - | TypeFlags::STILL_FURTHER_SPECIALIZABLE - } - ConstValue::Concrete(_) => flags, - } - } - } - } -} - -/// Generic arguments data. -#[derive(Clone, PartialEq, Eq, Hash, Visit, Fold, Zip)] -pub enum GenericArgData<I: Interner> { - /// Type argument - Ty(Ty<I>), - /// Lifetime argument - Lifetime(Lifetime<I>), - /// Constant argument - Const(Const<I>), -} - -impl<I: Interner> Copy for GenericArgData<I> -where - I::InternedType: Copy, - I::InternedLifetime: Copy, - I::InternedConst: Copy, -{ -} - -impl<I: Interner> GenericArgData<I> { - /// Create an interned type. - pub fn intern(self, interner: I) -> GenericArg<I> { - GenericArg::new(interner, self) - } -} - -/// A value with an associated variable kind. -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct WithKind<I: Interner, T> { - /// The associated variable kind. - pub kind: VariableKind<I>, - /// The wrapped value. - value: T, -} - -impl<I: Interner, T: Copy> Copy for WithKind<I, T> where I::InternedType: Copy {} - -impl<I: Interner, T> HasInterner for WithKind<I, T> { - type Interner = I; -} - -impl<I: Interner, T> From<WithKind<I, T>> for (VariableKind<I>, T) { - fn from(with_kind: WithKind<I, T>) -> Self { - (with_kind.kind, with_kind.value) - } -} - -impl<I: Interner, T> WithKind<I, T> { - /// Creates a `WithKind` from a variable kind and a value. - pub fn new(kind: VariableKind<I>, value: T) -> Self { - Self { kind, value } - } - - /// Maps the value in `WithKind`. - pub fn map<U, OP>(self, op: OP) -> WithKind<I, U> - where - OP: FnOnce(T) -> U, - { - WithKind { - kind: self.kind, - value: op(self.value), - } - } - - /// Maps a function taking `WithKind<I, &T>` over `&WithKind<I, T>`. - pub fn map_ref<U, OP>(&self, op: OP) -> WithKind<I, U> - where - OP: FnOnce(&T) -> U, - { - WithKind { - kind: self.kind.clone(), - value: op(&self.value), - } - } - - /// Extract the value, ignoring the variable kind. - pub fn skip_kind(&self) -> &T { - &self.value - } -} - -/// A variable kind with universe index. -#[allow(type_alias_bounds)] -pub type CanonicalVarKind<I: Interner> = WithKind<I, UniverseIndex>; - -/// An alias, which is a trait indirection such as a projection or opaque type. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub enum AliasTy<I: Interner> { - /// An associated type projection. - Projection(ProjectionTy<I>), - /// An opaque type. - Opaque(OpaqueTy<I>), -} - -impl<I: Interner> Copy for AliasTy<I> where I::InternedSubstitution: Copy {} - -impl<I: Interner> AliasTy<I> { - /// Create an interned type for this alias. - pub fn intern(self, interner: I) -> Ty<I> { - Ty::new(interner, self) - } - - /// Compute type flags for aliases - fn compute_flags(&self, interner: I) -> TypeFlags { - match self { - AliasTy::Projection(projection_ty) => { - TypeFlags::HAS_TY_PROJECTION | projection_ty.substitution.compute_flags(interner) - } - AliasTy::Opaque(opaque_ty) => { - TypeFlags::HAS_TY_OPAQUE | opaque_ty.substitution.compute_flags(interner) - } - } - } -} - -/// A projection `<P0 as TraitName<P1..Pn>>::AssocItem<Pn+1..Pm>`. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct ProjectionTy<I: Interner> { - /// The id for the associated type member. - pub associated_ty_id: AssocTypeId<I>, - /// The substitution for the projection. - pub substitution: Substitution<I>, -} - -impl<I: Interner> Copy for ProjectionTy<I> where I::InternedSubstitution: Copy {} - -impl<I: Interner> ProjectionTy<I> { - /// Gets the type parameters of the `Self` type in this alias type. - pub fn self_type_parameter(&self, interner: I) -> Ty<I> { - self.substitution - .iter(interner) - .find_map(move |p| p.ty(interner)) - .unwrap() - .clone() - } -} - -/// An opaque type `opaque type T<..>: Trait = HiddenTy`. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct OpaqueTy<I: Interner> { - /// The id for the opaque type. - pub opaque_ty_id: OpaqueTyId<I>, - /// The substitution for the opaque type. - pub substitution: Substitution<I>, -} - -impl<I: Interner> Copy for OpaqueTy<I> where I::InternedSubstitution: Copy {} - -/// A trait reference describes the relationship between a type and a trait. -/// This can be used in two forms: -/// - `P0: Trait<P1..Pn>` (e.g. `i32: Copy`), which mentions that the type -/// implements the trait. -/// - `<P0 as Trait<P1..Pn>>` (e.g. `i32 as Copy`), which casts the type to -/// that specific trait. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct TraitRef<I: Interner> { - /// The trait id. - pub trait_id: TraitId<I>, - /// The substitution, containing both the `Self` type and the parameters. - pub substitution: Substitution<I>, -} - -impl<I: Interner> Copy for TraitRef<I> where I::InternedSubstitution: Copy {} - -impl<I: Interner> TraitRef<I> { - /// Gets all type parameters in this trait ref, including `Self`. - pub fn type_parameters(&self, interner: I) -> impl Iterator<Item = Ty<I>> + '_ { - self.substitution - .iter(interner) - .filter_map(move |p| p.ty(interner)) - .cloned() - } - - /// Gets the type parameters of the `Self` type in this trait ref. - pub fn self_type_parameter(&self, interner: I) -> Ty<I> { - self.type_parameters(interner).next().unwrap() - } - - /// Construct a `FromEnv` using this trait ref. - pub fn from_env(self) -> FromEnv<I> { - FromEnv::Trait(self) - } - - /// Construct a `WellFormed` using this trait ref. - pub fn well_formed(self) -> WellFormed<I> { - WellFormed::Trait(self) - } -} - -/// Lifetime outlives, which for `'a: 'b`` checks that the lifetime `'a` -/// is a superset of the value of `'b`. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -#[allow(missing_docs)] -pub struct LifetimeOutlives<I: Interner> { - pub a: Lifetime<I>, - pub b: Lifetime<I>, -} - -impl<I: Interner> Copy for LifetimeOutlives<I> where I::InternedLifetime: Copy {} - -/// Type outlives, which for `T: 'a` checks that the type `T` -/// lives at least as long as the lifetime `'a` -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub struct TypeOutlives<I: Interner> { - /// The type which must outlive the given lifetime. - pub ty: Ty<I>, - /// The lifetime which the type must outlive. - pub lifetime: Lifetime<I>, -} - -impl<I: Interner> Copy for TypeOutlives<I> -where - I::InternedLifetime: Copy, - I::InternedType: Copy, -{ -} - -/// Where clauses that can be written by a Rust programmer. -#[derive(Clone, PartialEq, Eq, Hash, Fold, SuperVisit, HasInterner, Zip)] -pub enum WhereClause<I: Interner> { - /// Type implements a trait. - Implemented(TraitRef<I>), - /// Type is equal to an alias. - AliasEq(AliasEq<I>), - /// One lifetime outlives another. - LifetimeOutlives(LifetimeOutlives<I>), - /// Type outlives a lifetime. - TypeOutlives(TypeOutlives<I>), -} - -impl<I: Interner> Copy for WhereClause<I> -where - I::InternedSubstitution: Copy, - I::InternedLifetime: Copy, - I::InternedType: Copy, -{ -} - -/// Checks whether a type or trait ref is well-formed. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub enum WellFormed<I: Interner> { - /// A predicate which is true when some trait ref is well-formed. - /// For example, given the following trait definitions: - /// - /// ```notrust - /// trait Clone { ... } - /// trait Copy where Self: Clone { ... } - /// ``` - /// - /// then we have the following rule: - /// - /// ```notrust - /// WellFormed(?Self: Copy) :- ?Self: Copy, WellFormed(?Self: Clone) - /// ``` - Trait(TraitRef<I>), - - /// A predicate which is true when some type is well-formed. - /// For example, given the following type definition: - /// - /// ```notrust - /// struct Set<K> where K: Hash { - /// ... - /// } - /// ``` - /// - /// then we have the following rule: `WellFormedTy(Set<K>) :- Implemented(K: Hash)`. - Ty(Ty<I>), -} - -impl<I: Interner> Copy for WellFormed<I> -where - I::InternedType: Copy, - I::InternedSubstitution: Copy, -{ -} - -/// Checks whether a type or trait ref can be derived from the contents of the environment. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub enum FromEnv<I: Interner> { - /// A predicate which enables deriving everything which should be true if we *know* that - /// some trait ref is well-formed. For example given the above trait definitions, we can use - /// `FromEnv(T: Copy)` to derive that `T: Clone`, like in: - /// - /// ```notrust - /// forall<T> { - /// if (FromEnv(T: Copy)) { - /// T: Clone - /// } - /// } - /// ``` - Trait(TraitRef<I>), - - /// A predicate which enables deriving everything which should be true if we *know* that - /// some type is well-formed. For example given the above type definition, we can use - /// `FromEnv(Set<K>)` to derive that `K: Hash`, like in: - /// - /// ```notrust - /// forall<K> { - /// if (FromEnv(Set<K>)) { - /// K: Hash - /// } - /// } - /// ``` - Ty(Ty<I>), -} - -impl<I: Interner> Copy for FromEnv<I> -where - I::InternedType: Copy, - I::InternedSubstitution: Copy, -{ -} - -/// A "domain goal" is a goal that is directly about Rust, rather than a pure -/// logical statement. As much as possible, the Chalk solver should avoid -/// decomposing this enum, and instead treat its values opaquely. -#[derive(Clone, PartialEq, Eq, Hash, Fold, SuperVisit, HasInterner, Zip)] -pub enum DomainGoal<I: Interner> { - /// Simple goal that is true if the where clause is true. - Holds(WhereClause<I>), - - /// True if the type or trait ref is well-formed. - WellFormed(WellFormed<I>), - - /// True if the trait ref can be derived from in-scope where clauses. - FromEnv(FromEnv<I>), - - /// True if the alias type can be normalized to some other type - Normalize(Normalize<I>), - - /// True if a type is considered to have been "defined" by the current crate. This is true for - /// a `struct Foo { }` but false for a `#[upstream] struct Foo { }`. However, for fundamental types - /// like `Box<T>`, it is true if `T` is local. - IsLocal(Ty<I>), - - /// True if a type is *not* considered to have been "defined" by the current crate. This is - /// false for a `struct Foo { }` but true for a `#[upstream] struct Foo { }`. However, for - /// fundamental types like `Box<T>`, it is true if `T` is upstream. - IsUpstream(Ty<I>), - - /// True if a type and its input types are fully visible, known types. That is, there are no - /// unknown type parameters anywhere in this type. - /// - /// More formally, for each struct S<P0..Pn>: - /// forall<P0..Pn> { - /// IsFullyVisible(S<P0...Pn>) :- - /// IsFullyVisible(P0), - /// ... - /// IsFullyVisible(Pn) - /// } - /// - /// Note that any of these types can have lifetimes in their parameters too, but we only - /// consider type parameters. - IsFullyVisible(Ty<I>), - - /// Used to dictate when trait impls are allowed in the current (local) crate based on the - /// orphan rules. - /// - /// `LocalImplAllowed(T: Trait)` is true if the type T is allowed to impl trait Trait in - /// the current crate. Under the current rules, this is unconditionally true for all types if - /// the Trait is considered to be "defined" in the current crate. If that is not the case, then - /// `LocalImplAllowed(T: Trait)` can still be true if `IsLocal(T)` is true. - LocalImplAllowed(TraitRef<I>), - - /// Used to activate the "compatible modality" rules. Rules that introduce predicates that have - /// to do with "all compatible universes" should depend on this clause so that they only apply - /// if this is present. - Compatible, - - /// Used to indicate that a given type is in a downstream crate. Downstream crates contain the - /// current crate at some level of their dependencies. - /// - /// Since chalk does not actually see downstream types, this is usually introduced with - /// implication on a fresh, universally quantified type. - /// - /// forall<T> { if (DownstreamType(T)) { /* ... */ } } - /// - /// This makes a new type `T` available and makes `DownstreamType(T)` provable for that type. - DownstreamType(Ty<I>), - - /// Used to activate the "reveal mode", in which opaque (`impl Trait`) types can be equated - /// to their actual type. - Reveal, - - /// Used to indicate that a trait is object safe. - ObjectSafe(TraitId<I>), -} - -impl<I: Interner> Copy for DomainGoal<I> -where - I::InternedSubstitution: Copy, - I::InternedLifetime: Copy, - I::InternedType: Copy, -{ -} - -/// A where clause that can contain `forall<>` or `exists<>` quantifiers. -pub type QuantifiedWhereClause<I> = Binders<WhereClause<I>>; - -impl<I: Interner> WhereClause<I> { - /// Turn a where clause into the WF version of it i.e.: - /// * `Implemented(T: Trait)` maps to `WellFormed(T: Trait)` - /// * `ProjectionEq(<T as Trait>::Item = Foo)` maps to `WellFormed(<T as Trait>::Item = Foo)` - /// * any other clause maps to itself - pub fn into_well_formed_goal(self, interner: I) -> DomainGoal<I> { - match self { - WhereClause::Implemented(trait_ref) => WellFormed::Trait(trait_ref).cast(interner), - wc => wc.cast(interner), - } - } - - /// Same as `into_well_formed_goal` but with the `FromEnv` predicate instead of `WellFormed`. - pub fn into_from_env_goal(self, interner: I) -> DomainGoal<I> { - match self { - WhereClause::Implemented(trait_ref) => FromEnv::Trait(trait_ref).cast(interner), - wc => wc.cast(interner), - } - } - - /// If where clause is a `TraitRef`, returns its trait id. - pub fn trait_id(&self) -> Option<TraitId<I>> { - match self { - WhereClause::Implemented(trait_ref) => Some(trait_ref.trait_id), - WhereClause::AliasEq(_) => None, - WhereClause::LifetimeOutlives(_) => None, - WhereClause::TypeOutlives(_) => None, - } - } -} - -impl<I: Interner> QuantifiedWhereClause<I> { - /// As with `WhereClause::into_well_formed_goal`, but for a - /// quantified where clause. For example, `forall<T> { - /// Implemented(T: Trait)}` would map to `forall<T> { - /// WellFormed(T: Trait) }`. - pub fn into_well_formed_goal(self, interner: I) -> Binders<DomainGoal<I>> { - self.map(|wc| wc.into_well_formed_goal(interner)) - } - - /// As with `WhereClause::into_from_env_goal`, but mapped over any - /// binders. For example, `forall<T> { - /// Implemented(T: Trait)}` would map to `forall<T> { - /// FromEnv(T: Trait) }`. - pub fn into_from_env_goal(self, interner: I) -> Binders<DomainGoal<I>> { - self.map(|wc| wc.into_from_env_goal(interner)) - } - - /// If the underlying where clause is a `TraitRef`, returns its trait id. - pub fn trait_id(&self) -> Option<TraitId<I>> { - self.skip_binders().trait_id() - } -} - -impl<I: Interner> DomainGoal<I> { - /// Convert `Implemented(...)` into `FromEnv(...)`, but leave other - /// goals unchanged. - pub fn into_from_env_goal(self, interner: I) -> DomainGoal<I> { - match self { - DomainGoal::Holds(wc) => wc.into_from_env_goal(interner), - goal => goal, - } - } - - /// Lists generic arguments that are inputs to this domain goal. - pub fn inputs(&self, interner: I) -> Vec<GenericArg<I>> { - match self { - DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => { - vec![GenericArgData::Ty(alias_eq.alias.clone().intern(interner)).intern(interner)] - } - _ => Vec::new(), - } - } -} - -/// Equality goal: tries to prove that two values are equal. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, Zip)] -#[allow(missing_docs)] -pub struct EqGoal<I: Interner> { - pub a: GenericArg<I>, - pub b: GenericArg<I>, -} - -impl<I: Interner> Copy for EqGoal<I> where I::InternedGenericArg: Copy {} - -/// Subtype goal: tries to prove that `a` is a subtype of `b` -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, Zip)] -#[allow(missing_docs)] -pub struct SubtypeGoal<I: Interner> { - pub a: Ty<I>, - pub b: Ty<I>, -} - -impl<I: Interner> Copy for SubtypeGoal<I> where I::InternedType: Copy {} - -/// Proves that the given type alias **normalizes** to the given -/// type. A projection `T::Foo` normalizes to the type `U` if we can -/// **match it to an impl** and that impl has a `type Foo = V` where -/// `U = V`. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, Zip)] -#[allow(missing_docs)] -pub struct Normalize<I: Interner> { - pub alias: AliasTy<I>, - pub ty: Ty<I>, -} - -impl<I: Interner> Copy for Normalize<I> -where - I::InternedSubstitution: Copy, - I::InternedType: Copy, -{ -} - -/// Proves **equality** between an alias and a type. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, Zip)] -#[allow(missing_docs)] -pub struct AliasEq<I: Interner> { - pub alias: AliasTy<I>, - pub ty: Ty<I>, -} - -impl<I: Interner> Copy for AliasEq<I> -where - I::InternedSubstitution: Copy, - I::InternedType: Copy, -{ -} - -impl<I: Interner> HasInterner for AliasEq<I> { - type Interner = I; -} - -/// Indicates that the `value` is universally quantified over `N` -/// parameters of the given kinds, where `N == self.binders.len()`. A -/// variable with depth `i < N` refers to the value at -/// `self.binders[i]`. Variables with depth `>= N` are free. -/// -/// (IOW, we use deBruijn indices, where binders are introduced in reverse order -/// of `self.binders`.) -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Binders<T: HasInterner> { - /// The binders that quantify over the value. - pub binders: VariableKinds<T::Interner>, - - /// The value being quantified over. - value: T, -} - -impl<T: HasInterner + Copy> Copy for Binders<T> where - <T::Interner as Interner>::InternedVariableKinds: Copy -{ -} - -impl<T: HasInterner> HasInterner for Binders<T> { - type Interner = T::Interner; -} - -impl<T: Clone + HasInterner> Binders<&T> { - /// Converts a `Binders<&T>` to a `Binders<T>` by cloning `T`. - pub fn cloned(self) -> Binders<T> { - self.map(Clone::clone) - } -} - -impl<T: HasInterner> Binders<T> { - /// Create new binders. - pub fn new(binders: VariableKinds<T::Interner>, value: T) -> Self { - Self { binders, value } - } - - /// Wraps the given value in a binder without variables, i.e. `for<> - /// (value)`. Since our deBruijn indices count binders, not variables, this - /// is sometimes useful. - pub fn empty(interner: T::Interner, value: T) -> Self { - let binders = VariableKinds::empty(interner); - Self { binders, value } - } - - /// Skips the binder and returns the "bound" value. This is a - /// risky thing to do because it's easy to get confused about - /// De Bruijn indices and the like. `skip_binder` is only valid - /// when you are either extracting data that has nothing to - /// do with bound vars, or you are being very careful about - /// your depth accounting. - /// - /// Some examples where `skip_binder` is reasonable: - /// - /// - extracting the `TraitId` from a TraitRef; - /// - checking if there are any fields in a StructDatum - pub fn skip_binders(&self) -> &T { - &self.value - } - - /// Skips the binder and returns the "bound" value as well as the skipped free variables. This - /// is just as risky as [`skip_binders`][Self::skip_binders]. - pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds<T::Interner>) { - (self.value, self.binders) - } - - /// Converts `&Binders<T>` to `Binders<&T>`. Produces new `Binders` - /// with cloned quantifiers containing a reference to the original - /// value, leaving the original in place. - pub fn as_ref(&self) -> Binders<&T> { - Binders { - binders: self.binders.clone(), - value: &self.value, - } - } - - /// Maps the binders by applying a function. - pub fn map<U, OP>(self, op: OP) -> Binders<U> - where - OP: FnOnce(T) -> U, - U: HasInterner<Interner = T::Interner>, - { - let value = op(self.value); - Binders { - binders: self.binders, - value, - } - } - - /// Transforms the inner value according to the given function; returns - /// `None` if the function returns `None`. - pub fn filter_map<U, OP>(self, op: OP) -> Option<Binders<U>> - where - OP: FnOnce(T) -> Option<U>, - U: HasInterner<Interner = T::Interner>, - { - let value = op(self.value)?; - Some(Binders { - binders: self.binders, - value, - }) - } - - /// Maps a function taking `Binders<&T>` over `&Binders<T>`. - pub fn map_ref<'a, U, OP>(&'a self, op: OP) -> Binders<U> - where - OP: FnOnce(&'a T) -> U, - U: HasInterner<Interner = T::Interner>, - { - self.as_ref().map(op) - } - - /// Creates a `Substitution` containing bound vars such that applying this - /// substitution will not change the value, i.e. `^0.0, ^0.1, ^0.2` and so - /// on. - pub fn identity_substitution(&self, interner: T::Interner) -> Substitution<T::Interner> { - Substitution::from_iter( - interner, - self.binders - .iter(interner) - .enumerate() - .map(|p| p.to_generic_arg(interner)), - ) - } - - /// Creates a fresh binders that contains a single type - /// variable. The result of the closure will be embedded in this - /// binder. Note that you should be careful with what you return - /// from the closure to account for the binder that will be added. - /// - /// XXX FIXME -- this is potentially a pretty footgun-y function. - pub fn with_fresh_type_var( - interner: T::Interner, - op: impl FnOnce(Ty<T::Interner>) -> T, - ) -> Binders<T> { - // The new variable is at the front and everything afterwards is shifted up by 1 - let new_var = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(interner); - let value = op(new_var); - let binders = VariableKinds::from1(interner, VariableKind::Ty(TyVariableKind::General)); - Binders { binders, value } - } - - /// Returns the number of binders. - pub fn len(&self, interner: T::Interner) -> usize { - self.binders.len(interner) - } -} - -impl<T, I> Binders<Binders<T>> -where - T: Fold<I> + HasInterner<Interner = I>, - T::Result: HasInterner<Interner = I>, - I: Interner, -{ - /// This turns two levels of binders (`for<A> for<B>`) into one level (`for<A, B>`). - pub fn fuse_binders(self, interner: T::Interner) -> Binders<T::Result> { - let num_binders = self.len(interner); - // generate a substitution to shift the indexes of the inner binder: - let subst = Substitution::from_iter( - interner, - self.value - .binders - .iter(interner) - .enumerate() - .map(|(i, pk)| (i + num_binders, pk).to_generic_arg(interner)), - ); - let binders = VariableKinds::from_iter( - interner, - self.binders - .iter(interner) - .chain(self.value.binders.iter(interner)) - .cloned(), - ); - let value = self.value.substitute(interner, &subst); - Binders { binders, value } - } -} - -impl<T: HasInterner> From<Binders<T>> for (VariableKinds<T::Interner>, T) { - fn from(binders: Binders<T>) -> Self { - (binders.binders, binders.value) - } -} - -impl<T, I> Binders<T> -where - T: Fold<I> + HasInterner<Interner = I>, - I: Interner, -{ - /// Substitute `parameters` for the variables introduced by these - /// binders. So if the binders represent (e.g.) `<X, Y> { T }` and - /// parameters is the slice `[A, B]`, then returns `[X => A, Y => - /// B] T`. - pub fn substitute( - self, - interner: I, - parameters: &(impl AsParameters<I> + ?Sized), - ) -> T::Result { - let parameters = parameters.as_parameters(interner); - assert_eq!(self.binders.len(interner), parameters.len()); - Subst::apply(interner, parameters, self.value) - } -} - -/// Allows iterating over a Binders<Vec<T>>, for instance. -/// Each element will include the same set of parameter bounds. -impl<V, U> IntoIterator for Binders<V> -where - V: HasInterner + IntoIterator<Item = U>, - U: HasInterner<Interner = V::Interner>, -{ - type Item = Binders<U>; - type IntoIter = BindersIntoIterator<V>; - - fn into_iter(self) -> Self::IntoIter { - BindersIntoIterator { - iter: self.value.into_iter(), - binders: self.binders, - } - } -} - -/// `IntoIterator` for binders. -pub struct BindersIntoIterator<V: HasInterner + IntoIterator> { - iter: <V as IntoIterator>::IntoIter, - binders: VariableKinds<V::Interner>, -} - -impl<V> Iterator for BindersIntoIterator<V> -where - V: HasInterner + IntoIterator, - <V as IntoIterator>::Item: HasInterner<Interner = V::Interner>, -{ - type Item = Binders<<V as IntoIterator>::Item>; - fn next(&mut self) -> Option<Self::Item> { - self.iter - .next() - .map(|v| Binders::new(self.binders.clone(), v)) - } -} - -/// Represents one clause of the form `consequence :- conditions` where -/// `conditions = cond_1 && cond_2 && ...` is the conjunction of the individual -/// conditions. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub struct ProgramClauseImplication<I: Interner> { - /// The consequence of the clause, which holds if the conditions holds. - pub consequence: DomainGoal<I>, - - /// The condition goals that should hold. - pub conditions: Goals<I>, - - /// The lifetime constraints that should be proven. - pub constraints: Constraints<I>, - - /// The relative priority of the implication. - pub priority: ClausePriority, -} - -/// Specifies how important an implication is. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum ClausePriority { - /// High priority, the solver should prioritize this. - High, - - /// Low priority, this implication has lower chance to be relevant to the goal. - Low, -} - -impl std::ops::BitAnd for ClausePriority { - type Output = ClausePriority; - fn bitand(self, rhs: ClausePriority) -> Self::Output { - match (self, rhs) { - (ClausePriority::High, ClausePriority::High) => ClausePriority::High, - _ => ClausePriority::Low, - } - } -} - -/// Contains the data for a program clause. -#[derive(Clone, PartialEq, Eq, Hash, Fold, HasInterner, Zip)] -pub struct ProgramClauseData<I: Interner>(pub Binders<ProgramClauseImplication<I>>); - -impl<I: Interner> ProgramClauseImplication<I> { - /// Change the implication into an application holding a `FromEnv` goal. - pub fn into_from_env_clause(self, interner: I) -> ProgramClauseImplication<I> { - if self.conditions.is_empty(interner) { - ProgramClauseImplication { - consequence: self.consequence.into_from_env_goal(interner), - conditions: self.conditions.clone(), - constraints: self.constraints.clone(), - priority: self.priority, - } - } else { - self - } - } -} - -impl<I: Interner> ProgramClauseData<I> { - /// Change the program clause data into a `FromEnv` program clause. - pub fn into_from_env_clause(self, interner: I) -> ProgramClauseData<I> { - ProgramClauseData(self.0.map(|i| i.into_from_env_clause(interner))) - } - - /// Intern the program clause data. - pub fn intern(self, interner: I) -> ProgramClause<I> { - ProgramClause { - interned: interner.intern_program_clause(self), - } - } -} - -/// A program clause is a logic expression used to describe a part of the program. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -pub struct ProgramClause<I: Interner> { - interned: I::InternedProgramClause, -} - -impl<I: Interner> ProgramClause<I> { - /// Create a new program clause using `ProgramClauseData`. - pub fn new(interner: I, clause: ProgramClauseData<I>) -> Self { - let interned = interner.intern_program_clause(clause); - Self { interned } - } - - /// Change the clause into a `FromEnv` clause. - pub fn into_from_env_clause(self, interner: I) -> ProgramClause<I> { - let program_clause_data = self.data(interner); - let new_clause = program_clause_data.clone().into_from_env_clause(interner); - Self::new(interner, new_clause) - } - - /// Get the interned program clause. - pub fn interned(&self) -> &I::InternedProgramClause { - &self.interned - } - - /// Get the program clause data. - pub fn data(&self, interner: I) -> &ProgramClauseData<I> { - interner.program_clause_data(&self.interned) - } -} - -/// Wraps a "canonicalized item". Items are canonicalized as follows: -/// -/// All unresolved existential variables are "renumbered" according to their -/// first appearance; the kind/universe of the variable is recorded in the -/// `binders` field. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Canonical<T: HasInterner> { - /// The item that is canonicalized. - pub value: T, - - /// The kind/universe of the variable. - pub binders: CanonicalVarKinds<T::Interner>, -} - -impl<T: HasInterner> HasInterner for Canonical<T> { - type Interner = T::Interner; -} - -/// A "universe canonical" value. This is a wrapper around a -/// `Canonical`, indicating that the universes within have been -/// "renumbered" to start from 0 and collapse unimportant -/// distinctions. -/// -/// To produce one of these values, use the `u_canonicalize` method. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct UCanonical<T: HasInterner> { - /// The wrapped `Canonical`. - pub canonical: Canonical<T>, - - /// The number of universes that have been collapsed. - pub universes: usize, -} - -impl<T: HasInterner> UCanonical<T> { - /// Checks whether the universe canonical value is a trivial - /// substitution (e.g. an identity substitution). - pub fn is_trivial_substitution( - &self, - interner: T::Interner, - canonical_subst: &Canonical<AnswerSubst<T::Interner>>, - ) -> bool { - let subst = &canonical_subst.value.subst; - assert_eq!( - self.canonical.binders.len(interner), - subst.as_slice(interner).len() - ); - subst.is_identity_subst(interner) - } - - /// Creates an identity substitution. - pub fn trivial_substitution(&self, interner: T::Interner) -> Substitution<T::Interner> { - let binders = &self.canonical.binders; - Substitution::from_iter( - interner, - binders - .iter(interner) - .enumerate() - .map(|(index, pk)| { - let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, index); - match &pk.kind { - VariableKind::Ty(_) => { - GenericArgData::Ty(TyKind::BoundVar(bound_var).intern(interner)) - .intern(interner) - } - VariableKind::Lifetime => GenericArgData::Lifetime( - LifetimeData::BoundVar(bound_var).intern(interner), - ) - .intern(interner), - VariableKind::Const(ty) => GenericArgData::Const( - ConstData { - ty: ty.clone(), - value: ConstValue::BoundVar(bound_var), - } - .intern(interner), - ) - .intern(interner), - } - }) - .collect::<Vec<_>>(), - ) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] -/// A general goal; this is the full range of questions you can pose to Chalk. -pub struct Goal<I: Interner> { - interned: I::InternedGoal, -} - -impl<I: Interner> Goal<I> { - /// Create a new goal using `GoalData`. - pub fn new(interner: I, interned: GoalData<I>) -> Self { - let interned = I::intern_goal(interner, interned); - Self { interned } - } - - /// Gets the interned goal. - pub fn interned(&self) -> &I::InternedGoal { - &self.interned - } - - /// Gets the interned goal data. - pub fn data(&self, interner: I) -> &GoalData<I> { - interner.goal_data(&self.interned) - } - - /// Create a goal using a `forall` or `exists` quantifier. - pub fn quantify(self, interner: I, kind: QuantifierKind, binders: VariableKinds<I>) -> Goal<I> { - GoalData::Quantified(kind, Binders::new(binders, self)).intern(interner) - } - - /// Takes a goal `G` and turns it into `not { G }`. - pub fn negate(self, interner: I) -> Self { - GoalData::Not(self).intern(interner) - } - - /// Takes a goal `G` and turns it into `compatible { G }`. - pub fn compatible(self, interner: I) -> Self { - // compatible { G } desugars into: forall<T> { if (Compatible, DownstreamType(T)) { G } } - // This activates the compatible modality rules and introduces an anonymous downstream type - GoalData::Quantified( - QuantifierKind::ForAll, - Binders::with_fresh_type_var(interner, |ty| { - GoalData::Implies( - ProgramClauses::from_iter( - interner, - vec![DomainGoal::Compatible, DomainGoal::DownstreamType(ty)], - ), - self.shifted_in(interner), - ) - .intern(interner) - }), - ) - .intern(interner) - } - - /// Create an implication goal that holds if the predicates are true. - pub fn implied_by(self, interner: I, predicates: ProgramClauses<I>) -> Goal<I> { - GoalData::Implies(predicates, self).intern(interner) - } - - /// True if this goal is "trivially true" -- i.e., no work is - /// required to prove it. - pub fn is_trivially_true(&self, interner: I) -> bool { - match self.data(interner) { - GoalData::All(goals) => goals.is_empty(interner), - _ => false, - } - } -} - -impl<I> Goal<I> -where - I: Interner, -{ - /// Creates a single goal that only holds if a list of goals holds. - pub fn all<II>(interner: I, iter: II) -> Self - where - II: IntoIterator<Item = Goal<I>>, - { - let mut iter = iter.into_iter(); - if let Some(goal0) = iter.next() { - if let Some(goal1) = iter.next() { - // More than one goal to prove - let goals = Goals::from_iter( - interner, - Some(goal0).into_iter().chain(Some(goal1)).chain(iter), - ); - GoalData::All(goals).intern(interner) - } else { - // One goal to prove - goal0 - } - } else { - // No goals to prove, always true - GoalData::All(Goals::empty(interner)).intern(interner) - } - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -/// A general goal; this is the full range of questions you can pose to Chalk. -pub enum GoalData<I: Interner> { - /// Introduces a binding at depth 0, shifting other bindings up - /// (deBruijn index). - Quantified(QuantifierKind, Binders<Goal<I>>), - - /// A goal that holds given some clauses (like an if-statement). - Implies(ProgramClauses<I>, Goal<I>), - - /// List of goals that all should hold. - All(Goals<I>), - - /// Negation: the inner goal should not hold. - Not(Goal<I>), - - /// Make two things equal; the rules for doing so are well known to the logic - EqGoal(EqGoal<I>), - - /// Make one thing a subtype of another; the rules for doing so are well known to the logic - SubtypeGoal(SubtypeGoal<I>), - - /// A "domain goal" indicates some base sort of goal that can be - /// proven via program clauses - DomainGoal(DomainGoal<I>), - - /// Indicates something that cannot be proven to be true or false - /// definitively. This can occur with overflow but also with - /// unifications of skolemized variables like `forall<X,Y> { X = Y - /// }`. Of course, that statement is false, as there exist types - /// X, Y where `X = Y` is not true. But we treat it as "cannot - /// prove" so that `forall<X,Y> { not { X = Y } }` also winds up - /// as cannot prove. - CannotProve, -} - -impl<I: Interner> Copy for GoalData<I> -where - I::InternedType: Copy, - I::InternedLifetime: Copy, - I::InternedGenericArg: Copy, - I::InternedSubstitution: Copy, - I::InternedGoal: Copy, - I::InternedGoals: Copy, - I::InternedProgramClauses: Copy, - I::InternedVariableKinds: Copy, -{ -} - -impl<I: Interner> GoalData<I> { - /// Create an interned goal. - pub fn intern(self, interner: I) -> Goal<I> { - Goal::new(interner, self) - } -} - -/// Kinds of quantifiers in the logic, such as `forall` and `exists`. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum QuantifierKind { - /// Universal quantifier `ForAll`. - /// - /// A formula with the universal quantifier `forall(x). P(x)` is satisfiable - /// if and only if the subformula `P(x)` is true for all possible values for x. - ForAll, - - /// Existential quantifier `Exists`. - /// - /// A formula with the existential quantifier `exists(x). P(x)` is satisfiable - /// if and only if there exists at least one value for all possible values of x - /// which satisfies the subformula `P(x)`. - - /// In the context of chalk, the existential quantifier usually demands the - /// existence of exactly one instance (i.e. type) that satisfies the formula - /// (i.e. type constraints). More than one instance means that the result is ambiguous. - Exists, -} - -/// A constraint on lifetimes. -/// -/// When we search for solutions within the trait system, we essentially ignore -/// lifetime constraints, instead gathering them up to return with our solution -/// for later checking. This allows for decoupling between type and region -/// checking in the compiler. -#[derive(Clone, PartialEq, Eq, Hash, Fold, Visit, HasInterner, Zip)] -pub enum Constraint<I: Interner> { - /// Outlives constraint `'a: 'b`, indicating that the value of `'a` must be - /// a superset of the value of `'b`. - LifetimeOutlives(Lifetime<I>, Lifetime<I>), - - /// Type outlives constraint `T: 'a`, indicating that the type `T` must live - /// at least as long as the value of `'a`. - TypeOutlives(Ty<I>, Lifetime<I>), -} - -impl<I: Interner> Copy for Constraint<I> -where - I::InternedLifetime: Copy, - I::InternedType: Copy, -{ -} - -impl<I: Interner> Substitution<I> { - /// A substitution is an **identity substitution** if it looks - /// like this - /// - /// ```text - /// ?0 := ?0 - /// ?1 := ?1 - /// ?2 := ?2 - /// ... - /// ``` - /// - /// Basically, each value is mapped to a type or lifetime with its - /// same index. - pub fn is_identity_subst(&self, interner: I) -> bool { - self.iter(interner).zip(0..).all(|(generic_arg, index)| { - let index_db = BoundVar::new(DebruijnIndex::INNERMOST, index); - match generic_arg.data(interner) { - GenericArgData::Ty(ty) => match ty.kind(interner) { - TyKind::BoundVar(depth) => index_db == *depth, - _ => false, - }, - GenericArgData::Lifetime(lifetime) => match lifetime.data(interner) { - LifetimeData::BoundVar(depth) => index_db == *depth, - _ => false, - }, - GenericArgData::Const(constant) => match &constant.data(interner).value { - ConstValue::BoundVar(depth) => index_db == *depth, - _ => false, - }, - } - }) - } - - /// Apply the substitution to a value. - pub fn apply<T>(&self, value: T, interner: I) -> T::Result - where - T: Fold<I>, - { - Substitute::apply(self, value, interner) - } - - /// Gets an iterator of all type parameters. - pub fn type_parameters(&self, interner: I) -> impl Iterator<Item = Ty<I>> + '_ { - self.iter(interner) - .filter_map(move |p| p.ty(interner)) - .cloned() - } - - /// Compute type flags for Substitution<I> - fn compute_flags(&self, interner: I) -> TypeFlags { - let mut flags = TypeFlags::empty(); - for generic_arg in self.iter(interner) { - flags |= generic_arg.compute_flags(interner); - } - flags - } -} - -struct SubstFolder<'i, I: Interner, A: AsParameters<I>> { - interner: I, - subst: &'i A, -} - -impl<I: Interner, A: AsParameters<I>> SubstFolder<'_, I, A> { - /// Index into the list of parameters. - pub fn at(&self, index: usize) -> &GenericArg<I> { - let interner = self.interner; - &self.subst.as_parameters(interner)[index] - } -} - -/// Convert a value to a list of parameters. -pub trait AsParameters<I: Interner> { - /// Convert the current value to parameters. - fn as_parameters(&self, interner: I) -> &[GenericArg<I>]; -} - -impl<I: Interner> AsParameters<I> for Substitution<I> { - #[allow(unreachable_code, unused_variables)] - fn as_parameters(&self, interner: I) -> &[GenericArg<I>] { - self.as_slice(interner) - } -} - -impl<I: Interner> AsParameters<I> for [GenericArg<I>] { - fn as_parameters(&self, _interner: I) -> &[GenericArg<I>] { - self - } -} - -impl<I: Interner> AsParameters<I> for [GenericArg<I>; 1] { - fn as_parameters(&self, _interner: I) -> &[GenericArg<I>] { - self - } -} - -impl<I: Interner> AsParameters<I> for Vec<GenericArg<I>> { - fn as_parameters(&self, _interner: I) -> &[GenericArg<I>] { - self - } -} - -impl<T, I: Interner> AsParameters<I> for &T -where - T: ?Sized + AsParameters<I>, -{ - fn as_parameters(&self, interner: I) -> &[GenericArg<I>] { - T::as_parameters(self, interner) - } -} - -/// An extension trait to anything that can be represented as list of `GenericArg`s that signifies -/// that it can applied as a substituion to a value -pub trait Substitute<I: Interner>: AsParameters<I> { - /// Apply the substitution to a value. - fn apply<T: Fold<I>>(&self, value: T, interner: I) -> T::Result; -} - -impl<I: Interner, A: AsParameters<I>> Substitute<I> for A { - fn apply<T>(&self, value: T, interner: I) -> T::Result - where - T: Fold<I>, - { - value - .fold_with( - &mut &SubstFolder { - interner, - subst: self, - }, - DebruijnIndex::INNERMOST, - ) - .unwrap() - } -} - -/// Utility for converting a list of all the binders into scope -/// into references to those binders. Simply pair the binders with -/// the indices, and invoke `to_generic_arg()` on the `(binder, -/// index)` pair. The result will be a reference to a bound -/// variable of appropriate kind at the corresponding index. -pub trait ToGenericArg<I: Interner> { - /// Converts the binders in scope to references to those binders. - fn to_generic_arg(&self, interner: I) -> GenericArg<I> { - self.to_generic_arg_at_depth(interner, DebruijnIndex::INNERMOST) - } - - /// Converts the binders at the specified depth to references to those binders. - fn to_generic_arg_at_depth(&self, interner: I, debruijn: DebruijnIndex) -> GenericArg<I>; -} - -impl<'a, I: Interner> ToGenericArg<I> for (usize, &'a VariableKind<I>) { - fn to_generic_arg_at_depth(&self, interner: I, debruijn: DebruijnIndex) -> GenericArg<I> { - let &(index, binder) = self; - let bound_var = BoundVar::new(debruijn, index); - binder.to_bound_variable(interner, bound_var) - } -} - -impl<'i, I: Interner, A: AsParameters<I>> Folder<I> for &SubstFolder<'i, I, A> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn Folder<I, Error = Self::Error> { - self - } - - fn fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible<Ty<I>> { - assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); - let ty = self.at(bound_var.index); - let ty = ty.assert_ty_ref(self.interner()); - Ok(ty.clone().shifted_in_from(self.interner(), outer_binder)) - } - - fn fold_free_var_lifetime( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible<Lifetime<I>> { - assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); - let l = self.at(bound_var.index); - let l = l.assert_lifetime_ref(self.interner()); - Ok(l.clone().shifted_in_from(self.interner(), outer_binder)) - } - - fn fold_free_var_const( - &mut self, - _ty: Ty<I>, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible<Const<I>> { - assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); - let c = self.at(bound_var.index); - let c = c.assert_const_ref(self.interner()); - Ok(c.clone().shifted_in_from(self.interner(), outer_binder)) - } - - fn interner(&self) -> I { - self.interner - } -} - -macro_rules! interned_slice_common { - ($seq:ident, $data:ident => $elem:ty, $intern:ident => $interned:ident) => { - /// List of interned elements. - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)] - pub struct $seq<I: Interner> { - interned: I::$interned, - } - - impl<I: Interner> $seq<I> { - /// Get the interned elements. - pub fn interned(&self) -> &I::$interned { - &self.interned - } - - /// Returns a slice containing the elements. - pub fn as_slice(&self, interner: I) -> &[$elem] { - Interner::$data(interner, &self.interned) - } - - /// Index into the sequence. - pub fn at(&self, interner: I, index: usize) -> &$elem { - &self.as_slice(interner)[index] - } - - /// Create an empty sequence. - pub fn empty(interner: I) -> Self { - Self::from_iter(interner, None::<$elem>) - } - - /// Check whether this is an empty sequence. - pub fn is_empty(&self, interner: I) -> bool { - self.as_slice(interner).is_empty() - } - - /// Get an iterator over the elements of the sequence. - pub fn iter(&self, interner: I) -> std::slice::Iter<'_, $elem> { - self.as_slice(interner).iter() - } - - /// Get the length of the sequence. - pub fn len(&self, interner: I) -> usize { - self.as_slice(interner).len() - } - } - }; -} - -macro_rules! interned_slice { - ($seq:ident, $data:ident => $elem:ty, $intern:ident => $interned:ident) => { - interned_slice_common!($seq, $data => $elem, $intern => $interned); - - impl<I: Interner> $seq<I> { - /// Tries to create a sequence using an iterator of element-like things. - pub fn from_fallible<E>( - interner: I, - elements: impl IntoIterator<Item = Result<impl CastTo<$elem>, E>>, - ) -> Result<Self, E> { - Ok(Self { - interned: I::$intern(interner, elements.into_iter().casted(interner))?, - }) - } - - /// Create a sequence from elements - pub fn from_iter( - interner: I, - elements: impl IntoIterator<Item = impl CastTo<$elem>>, - ) -> Self { - Self::from_fallible( - interner, - elements - .into_iter() - .map(|el| -> Result<$elem, ()> { Ok(el.cast(interner)) }), - ) - .unwrap() - } - - /// Create a sequence from a single element. - pub fn from1(interner: I, element: impl CastTo<$elem>) -> Self { - Self::from_iter(interner, Some(element)) - } - } - }; -} - -interned_slice!( - QuantifiedWhereClauses, - quantified_where_clauses_data => QuantifiedWhereClause<I>, - intern_quantified_where_clauses => InternedQuantifiedWhereClauses -); - -interned_slice!( - ProgramClauses, - program_clauses_data => ProgramClause<I>, - intern_program_clauses => InternedProgramClauses -); - -interned_slice!( - VariableKinds, - variable_kinds_data => VariableKind<I>, - intern_generic_arg_kinds => InternedVariableKinds -); - -interned_slice!( - CanonicalVarKinds, - canonical_var_kinds_data => CanonicalVarKind<I>, - intern_canonical_var_kinds => InternedCanonicalVarKinds -); - -interned_slice!(Goals, goals_data => Goal<I>, intern_goals => InternedGoals); - -interned_slice!( - Constraints, - constraints_data => InEnvironment<Constraint<I>>, - intern_constraints => InternedConstraints -); - -interned_slice!( - Substitution, - substitution_data => GenericArg<I>, - intern_substitution => InternedSubstitution -); - -interned_slice_common!( - Variances, - variances_data => Variance, - intern_variance => InternedVariances -); - -impl<I: Interner> Variances<I> { - /// Tries to create a list of canonical variable kinds using an iterator. - pub fn from_fallible<E>( - interner: I, - variances: impl IntoIterator<Item = Result<Variance, E>>, - ) -> Result<Self, E> { - Ok(Variances { - interned: I::intern_variances(interner, variances.into_iter())?, - }) - } - - /// Creates a list of canonical variable kinds using an iterator. - pub fn from_iter(interner: I, variances: impl IntoIterator<Item = Variance>) -> Self { - Self::from_fallible( - interner, - variances - .into_iter() - .map(|p| -> Result<Variance, ()> { Ok(p) }), - ) - .unwrap() - } - - /// Creates a list of canonical variable kinds from a single canonical variable kind. - pub fn from1(interner: I, variance: Variance) -> Self { - Self::from_iter(interner, Some(variance)) - } -} - -/// Combines a substitution (`subst`) with a set of region constraints -/// (`constraints`). This represents the result of a query; the -/// substitution stores the values for the query's unknown variables, -/// and the constraints represents any region constraints that must -/// additionally be solved. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct ConstrainedSubst<I: Interner> { - /// The substitution that is being constrained. - /// - /// NB: The `is_trivial` routine relies on the fact that `subst` is folded first. - pub subst: Substitution<I>, - - /// Region constraints that constrain the substitution. - pub constraints: Constraints<I>, -} - -/// The resulting substitution after solving a goal. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)] -pub struct AnswerSubst<I: Interner> { - /// The substitution result. - /// - /// NB: The `is_trivial` routine relies on the fact that `subst` is folded first. - pub subst: Substitution<I>, - - /// List of constraints that are part of the answer. - pub constraints: Constraints<I>, - - /// Delayed subgoals, used when the solver answered with an (incomplete) `Answer` (instead of a `CompleteAnswer`). - pub delayed_subgoals: Vec<InEnvironment<Goal<I>>>, -} - -/// Logic to decide the Variance for a given subst -pub trait UnificationDatabase<I> -where - Self: std::fmt::Debug, - I: Interner, -{ - /// Gets the variances for the substitution of a fn def - fn fn_def_variance(&self, fn_def_id: FnDefId<I>) -> Variances<I>; - - /// Gets the variances for the substitution of a adt - fn adt_variance(&self, adt_id: AdtId<I>) -> Variances<I>; -} |