From 64d98f8ee037282c35007b64c2649055c56af1db Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:03 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- vendor/chalk-ir-0.87.0/src/cast.rs | 364 +++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 vendor/chalk-ir-0.87.0/src/cast.rs (limited to 'vendor/chalk-ir-0.87.0/src/cast.rs') diff --git a/vendor/chalk-ir-0.87.0/src/cast.rs b/vendor/chalk-ir-0.87.0/src/cast.rs new file mode 100644 index 000000000..0c6b682ca --- /dev/null +++ b/vendor/chalk-ir-0.87.0/src/cast.rs @@ -0,0 +1,364 @@ +//! Upcasts, to avoid writing out wrapper types. + +use crate::*; +use std::marker::PhantomData; + +/// The `Cast` trait is used to make annoying upcasts between +/// logically equivalent types that imply wrappers. For example, one +/// could convert a `DomainGoal` into a `Goal` by doing: +/// +/// ```ignore +/// let goal: Goal = domain_goal.cast(); +/// ``` +/// +/// This is equivalent to the more explicit: +/// +/// ```ignore +/// let goal: Goal = Goal::DomainGoal(domain_goal) +/// ``` +/// +/// Another useful trick is the `casted()` iterator adapter, which +/// casts each element in the iterator as it is produced (you must +/// have the `Caster` trait in scope for that). +/// +/// # Invariant +/// +/// `Cast` imposes a key invariant. You can only implement `T: +/// Cast` if both `T` and `U` have the same semantic meaning. Also, +/// as part of this, they should always use the same set of free +/// variables (the `Canonical` implementation, for example, relies on +/// that). +/// +/// # Iterators +/// +/// If you import the `Caster` trait, you can also write `.casted()` on an +/// iterator chain to cast every instance within. +/// +/// # Implementing Cast +/// +/// Do not implement `Cast` directly. Instead, implement `CastTo`. +/// This split setup allows us to write `foo.cast::()` to mean +/// "cast to T". +pub trait Cast: Sized { + /// Cast a value to type `U` using `CastTo`. + fn cast(self, interner: U::Interner) -> U + where + Self: CastTo, + U: HasInterner, + { + self.cast_to(interner) + } +} + +impl Cast for T {} + +/// The "helper" trait for `cast` that actually implements the +/// transformations. You can also use this if you want to have +/// functions that take (e.g.) an `impl CastTo>` or something +/// like that. +pub trait CastTo: Sized { + /// Cast a value to type `T`. + fn cast_to(self, interner: T::Interner) -> T; +} + +macro_rules! reflexive_impl { + (for($($t:tt)*) $u:ty) => { + impl<$($t)*> CastTo<$u> for $u { + fn cast_to(self, _interner: <$u as HasInterner>::Interner) -> $u { + self + } + } + }; + ($u:ty) => { + impl CastTo<$u> for $u { + fn cast_to(self, interner: <$u as HasInterner>::Interner) -> $u { + self + } + } + }; +} + +reflexive_impl!(for(I: Interner) TyKind); +reflexive_impl!(for(I: Interner) LifetimeData); +reflexive_impl!(for(I: Interner) ConstData); +reflexive_impl!(for(I: Interner) TraitRef); +reflexive_impl!(for(I: Interner) DomainGoal); +reflexive_impl!(for(I: Interner) Goal); +reflexive_impl!(for(I: Interner) WhereClause); +reflexive_impl!(for(I: Interner) ProgramClause); +reflexive_impl!(for(I: Interner) QuantifiedWhereClause); +reflexive_impl!(for(I: Interner) VariableKind); +reflexive_impl!(for(I: Interner) VariableKinds); +reflexive_impl!(for(I: Interner) CanonicalVarKind); +reflexive_impl!(for(I: Interner) CanonicalVarKinds); +reflexive_impl!(for(I: Interner) Constraint); + +impl CastTo> for TraitRef { + fn cast_to(self, _interner: I) -> WhereClause { + WhereClause::Implemented(self) + } +} + +impl CastTo> for AliasEq { + fn cast_to(self, _interner: I) -> WhereClause { + WhereClause::AliasEq(self) + } +} + +impl CastTo> for LifetimeOutlives { + fn cast_to(self, _interner: I) -> WhereClause { + WhereClause::LifetimeOutlives(self) + } +} + +impl CastTo> for TypeOutlives { + fn cast_to(self, _interner: I) -> WhereClause { + WhereClause::TypeOutlives(self) + } +} + +impl CastTo> for T +where + T: CastTo>, + I: Interner, +{ + fn cast_to(self, interner: I) -> DomainGoal { + DomainGoal::Holds(self.cast(interner)) + } +} + +impl CastTo> for T +where + T: CastTo>, +{ + fn cast_to(self, interner: I) -> Goal { + GoalData::DomainGoal(self.cast(interner)).intern(interner) + } +} + +impl CastTo> for Normalize { + fn cast_to(self, _interner: I) -> DomainGoal { + DomainGoal::Normalize(self) + } +} + +impl CastTo> for WellFormed { + fn cast_to(self, _interner: I) -> DomainGoal { + DomainGoal::WellFormed(self) + } +} + +impl CastTo> for FromEnv { + fn cast_to(self, _interner: I) -> DomainGoal { + DomainGoal::FromEnv(self) + } +} + +impl CastTo> for EqGoal { + fn cast_to(self, interner: I) -> Goal { + GoalData::EqGoal(self).intern(interner) + } +} + +impl CastTo> for SubtypeGoal { + fn cast_to(self, interner: I) -> Goal { + GoalData::SubtypeGoal(self).intern(interner) + } +} + +impl + CastTo>> CastTo> for Binders { + fn cast_to(self, interner: I) -> Goal { + GoalData::Quantified( + QuantifierKind::ForAll, + self.map(|bound| bound.cast(interner)), + ) + .intern(interner) + } +} + +impl CastTo> for AliasTy { + fn cast_to(self, _interner: I) -> TyKind { + TyKind::Alias(self) + } +} + +impl CastTo> for Ty { + fn cast_to(self, interner: I) -> GenericArg { + GenericArg::new(interner, GenericArgData::Ty(self)) + } +} + +impl CastTo> for Lifetime { + fn cast_to(self, interner: I) -> GenericArg { + GenericArg::new(interner, GenericArgData::Lifetime(self)) + } +} + +impl CastTo> for Const { + fn cast_to(self, interner: I) -> GenericArg { + GenericArg::new(interner, GenericArgData::Const(self)) + } +} + +impl CastTo> for GenericArg { + fn cast_to(self, _interner: I) -> GenericArg { + self + } +} + +impl CastTo> for T +where + T: CastTo>, + I: Interner, +{ + fn cast_to(self, interner: I) -> ProgramClause { + let implication = ProgramClauseImplication { + consequence: self.cast(interner), + conditions: Goals::empty(interner), + constraints: Constraints::empty(interner), + priority: ClausePriority::High, + }; + + ProgramClauseData(Binders::empty(interner, implication.shifted_in(interner))) + .intern(interner) + } +} + +impl CastTo> for Binders +where + I: Interner, + T: HasInterner + CastTo>, +{ + fn cast_to(self, interner: I) -> ProgramClause { + ProgramClauseData(self.map(|bound| ProgramClauseImplication { + consequence: bound.cast(interner), + conditions: Goals::empty(interner), + constraints: Constraints::empty(interner), + priority: ClausePriority::High, + })) + .intern(interner) + } +} + +impl CastTo> for Option +where + T: CastTo, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Option { + self.map(|v| v.cast(interner)) + } +} + +impl CastTo> for InEnvironment +where + T: HasInterner + CastTo, + U: HasInterner, + I: Interner, +{ + fn cast_to(self, interner: U::Interner) -> InEnvironment { + self.map(|v| v.cast(interner)) + } +} + +impl CastTo> for Result +where + T: CastTo, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Result { + self.map(|v| v.cast(interner)) + } +} + +impl HasInterner for Option +where + T: HasInterner, +{ + type Interner = T::Interner; +} + +impl HasInterner for Result +where + T: HasInterner, +{ + type Interner = T::Interner; +} + +impl CastTo> for Canonical +where + T: CastTo + HasInterner, + U: HasInterner, +{ + fn cast_to(self, interner: T::Interner) -> Canonical { + // Subtle point: It should be ok to re-use the binders here, + // because `cast()` never introduces new inference variables, + // nor changes the "substance" of the type we are working + // with. It just introduces new wrapper types. + Canonical { + value: self.value.cast(interner), + binders: self.binders.cast(interner), + } + } +} + +impl CastTo> for Vec +where + T: CastTo + HasInterner, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Vec { + self.into_iter().casted(interner).collect() + } +} + +impl CastTo for &T +where + T: Clone + HasInterner, +{ + fn cast_to(self, _interner: T::Interner) -> T { + self.clone() + } +} + +/// An iterator that casts each element to some other type. +pub struct Casted { + interner: U::Interner, + iterator: IT, + _cast: PhantomData, +} + +impl Iterator for Casted +where + IT::Item: CastTo, + U: HasInterner, +{ + type Item = U; + + fn next(&mut self) -> Option { + self.iterator.next().map(|item| item.cast_to(self.interner)) + } + + fn size_hint(&self) -> (usize, Option) { + self.iterator.size_hint() + } +} + +/// An iterator adapter that casts each element we are iterating over +/// to some other type. +pub trait Caster: Iterator + Sized { + /// Cast each element in this iterator. + fn casted(self, interner: U::Interner) -> Casted + where + Self::Item: CastTo, + U: HasInterner, + { + Casted { + interner, + iterator: self, + _cast: PhantomData, + } + } +} + +impl Caster for I where I: Iterator {} -- cgit v1.2.3