diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /vendor/chalk-ir-0.87.0/src/cast.rs | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chalk-ir-0.87.0/src/cast.rs')
-rw-r--r-- | vendor/chalk-ir-0.87.0/src/cast.rs | 364 |
1 files changed, 364 insertions, 0 deletions
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<U>` 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::<T>()` to mean +/// "cast to T". +pub trait Cast: Sized { + /// Cast a value to type `U` using `CastTo`. + fn cast<U>(self, interner: U::Interner) -> U + where + Self: CastTo<U>, + U: HasInterner, + { + self.cast_to(interner) + } +} + +impl<T> 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<Goal<_>>` or something +/// like that. +pub trait CastTo<T: HasInterner>: 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<I>); +reflexive_impl!(for(I: Interner) LifetimeData<I>); +reflexive_impl!(for(I: Interner) ConstData<I>); +reflexive_impl!(for(I: Interner) TraitRef<I>); +reflexive_impl!(for(I: Interner) DomainGoal<I>); +reflexive_impl!(for(I: Interner) Goal<I>); +reflexive_impl!(for(I: Interner) WhereClause<I>); +reflexive_impl!(for(I: Interner) ProgramClause<I>); +reflexive_impl!(for(I: Interner) QuantifiedWhereClause<I>); +reflexive_impl!(for(I: Interner) VariableKind<I>); +reflexive_impl!(for(I: Interner) VariableKinds<I>); +reflexive_impl!(for(I: Interner) CanonicalVarKind<I>); +reflexive_impl!(for(I: Interner) CanonicalVarKinds<I>); +reflexive_impl!(for(I: Interner) Constraint<I>); + +impl<I: Interner> CastTo<WhereClause<I>> for TraitRef<I> { + fn cast_to(self, _interner: I) -> WhereClause<I> { + WhereClause::Implemented(self) + } +} + +impl<I: Interner> CastTo<WhereClause<I>> for AliasEq<I> { + fn cast_to(self, _interner: I) -> WhereClause<I> { + WhereClause::AliasEq(self) + } +} + +impl<I: Interner> CastTo<WhereClause<I>> for LifetimeOutlives<I> { + fn cast_to(self, _interner: I) -> WhereClause<I> { + WhereClause::LifetimeOutlives(self) + } +} + +impl<I: Interner> CastTo<WhereClause<I>> for TypeOutlives<I> { + fn cast_to(self, _interner: I) -> WhereClause<I> { + WhereClause::TypeOutlives(self) + } +} + +impl<T, I> CastTo<DomainGoal<I>> for T +where + T: CastTo<WhereClause<I>>, + I: Interner, +{ + fn cast_to(self, interner: I) -> DomainGoal<I> { + DomainGoal::Holds(self.cast(interner)) + } +} + +impl<T, I: Interner> CastTo<Goal<I>> for T +where + T: CastTo<DomainGoal<I>>, +{ + fn cast_to(self, interner: I) -> Goal<I> { + GoalData::DomainGoal(self.cast(interner)).intern(interner) + } +} + +impl<I: Interner> CastTo<DomainGoal<I>> for Normalize<I> { + fn cast_to(self, _interner: I) -> DomainGoal<I> { + DomainGoal::Normalize(self) + } +} + +impl<I: Interner> CastTo<DomainGoal<I>> for WellFormed<I> { + fn cast_to(self, _interner: I) -> DomainGoal<I> { + DomainGoal::WellFormed(self) + } +} + +impl<I: Interner> CastTo<DomainGoal<I>> for FromEnv<I> { + fn cast_to(self, _interner: I) -> DomainGoal<I> { + DomainGoal::FromEnv(self) + } +} + +impl<I: Interner> CastTo<Goal<I>> for EqGoal<I> { + fn cast_to(self, interner: I) -> Goal<I> { + GoalData::EqGoal(self).intern(interner) + } +} + +impl<I: Interner> CastTo<Goal<I>> for SubtypeGoal<I> { + fn cast_to(self, interner: I) -> Goal<I> { + GoalData::SubtypeGoal(self).intern(interner) + } +} + +impl<I: Interner, T: HasInterner<Interner = I> + CastTo<Goal<I>>> CastTo<Goal<I>> for Binders<T> { + fn cast_to(self, interner: I) -> Goal<I> { + GoalData::Quantified( + QuantifierKind::ForAll, + self.map(|bound| bound.cast(interner)), + ) + .intern(interner) + } +} + +impl<I: Interner> CastTo<TyKind<I>> for AliasTy<I> { + fn cast_to(self, _interner: I) -> TyKind<I> { + TyKind::Alias(self) + } +} + +impl<I: Interner> CastTo<GenericArg<I>> for Ty<I> { + fn cast_to(self, interner: I) -> GenericArg<I> { + GenericArg::new(interner, GenericArgData::Ty(self)) + } +} + +impl<I: Interner> CastTo<GenericArg<I>> for Lifetime<I> { + fn cast_to(self, interner: I) -> GenericArg<I> { + GenericArg::new(interner, GenericArgData::Lifetime(self)) + } +} + +impl<I: Interner> CastTo<GenericArg<I>> for Const<I> { + fn cast_to(self, interner: I) -> GenericArg<I> { + GenericArg::new(interner, GenericArgData::Const(self)) + } +} + +impl<I: Interner> CastTo<GenericArg<I>> for GenericArg<I> { + fn cast_to(self, _interner: I) -> GenericArg<I> { + self + } +} + +impl<T, I> CastTo<ProgramClause<I>> for T +where + T: CastTo<DomainGoal<I>>, + I: Interner, +{ + fn cast_to(self, interner: I) -> ProgramClause<I> { + 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<I, T> CastTo<ProgramClause<I>> for Binders<T> +where + I: Interner, + T: HasInterner<Interner = I> + CastTo<DomainGoal<I>>, +{ + fn cast_to(self, interner: I) -> ProgramClause<I> { + ProgramClauseData(self.map(|bound| ProgramClauseImplication { + consequence: bound.cast(interner), + conditions: Goals::empty(interner), + constraints: Constraints::empty(interner), + priority: ClausePriority::High, + })) + .intern(interner) + } +} + +impl<T, U> CastTo<Option<U>> for Option<T> +where + T: CastTo<U>, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Option<U> { + self.map(|v| v.cast(interner)) + } +} + +impl<T, U, I> CastTo<InEnvironment<U>> for InEnvironment<T> +where + T: HasInterner<Interner = I> + CastTo<U>, + U: HasInterner<Interner = I>, + I: Interner, +{ + fn cast_to(self, interner: U::Interner) -> InEnvironment<U> { + self.map(|v| v.cast(interner)) + } +} + +impl<T, U, E> CastTo<Result<U, E>> for Result<T, E> +where + T: CastTo<U>, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Result<U, E> { + self.map(|v| v.cast(interner)) + } +} + +impl<T> HasInterner for Option<T> +where + T: HasInterner, +{ + type Interner = T::Interner; +} + +impl<T, E> HasInterner for Result<T, E> +where + T: HasInterner, +{ + type Interner = T::Interner; +} + +impl<T, U> CastTo<Canonical<U>> for Canonical<T> +where + T: CastTo<U> + HasInterner, + U: HasInterner<Interner = T::Interner>, +{ + fn cast_to(self, interner: T::Interner) -> Canonical<U> { + // 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<T, U> CastTo<Vec<U>> for Vec<T> +where + T: CastTo<U> + HasInterner, + U: HasInterner, +{ + fn cast_to(self, interner: U::Interner) -> Vec<U> { + self.into_iter().casted(interner).collect() + } +} + +impl<T> CastTo<T> 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<IT, U: HasInterner> { + interner: U::Interner, + iterator: IT, + _cast: PhantomData<U>, +} + +impl<IT: Iterator, U> Iterator for Casted<IT, U> +where + IT::Item: CastTo<U>, + U: HasInterner, +{ + type Item = U; + + fn next(&mut self) -> Option<Self::Item> { + self.iterator.next().map(|item| item.cast_to(self.interner)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + 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<U>(self, interner: U::Interner) -> Casted<Self, U> + where + Self::Item: CastTo<U>, + U: HasInterner, + { + Casted { + interner, + iterator: self, + _cast: PhantomData, + } + } +} + +impl<I> Caster for I where I: Iterator {} |