]>
git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir-0.55.0/src/cast.rs
1 //! Upcasts, to avoid writing out wrapper types.
4 use std
::marker
::PhantomData
;
6 /// The `Cast` trait is used to make annoying upcasts between
7 /// logically equivalent types that imply wrappers. For example, one
8 /// could convert a `DomainGoal` into a `Goal` by doing:
11 /// let goal: Goal = domain_goal.cast();
14 /// This is equivalent to the more explicit:
17 /// let goal: Goal = Goal::DomainGoal(domain_goal)
20 /// Another useful trick is the `casted()` iterator adapter, which
21 /// casts each element in the iterator as it is produced (you must
22 /// have the `Caster` trait in scope for that).
26 /// `Cast` imposes a key invariant. You can only implement `T:
27 /// Cast<U>` if both `T` and `U` have the same semantic meaning. Also,
28 /// as part of this, they should always use the same set of free
29 /// variables (the `Canonical` implementation, for example, relies on
34 /// If you import the `Caster` trait, you can also write `.casted()` on an
35 /// iterator chain to cast every instance within.
37 /// # Implementing Cast
39 /// Do not implement `Cast` directly. Instead, implement `CastTo`.
40 /// This split setup allows us to write `foo.cast::<T>()` to mean
42 pub trait Cast
: Sized
{
43 /// Cast a value to type `U` using `CastTo`.
44 fn cast
<U
>(self, interner
: &U
::Interner
) -> U
49 self.cast_to(interner
)
55 /// The "helper" trait for `cast` that actually implements the
56 /// transformations. You can also use this if you want to have
57 /// functions that take (e.g.) an `impl CastTo<Goal<_>>` or something
59 pub trait CastTo
<T
: HasInterner
>: Sized
{
60 /// Cast a value to type `T`.
61 fn cast_to(self, interner
: &T
::Interner
) -> T
;
64 macro_rules
! reflexive_impl
{
65 (for($
($t
:tt
)*) $u
:ty
) => {
66 impl<$
($t
)*> CastTo
<$u
> for $u
{
67 fn cast_to(self, _interner
: &<$u
as HasInterner
>::Interner
) -> $u
{
73 impl CastTo
<$u
> for $u
{
74 fn cast_to(self, interner
: &<$u
as HasInterner
>::Interner
) -> $u
{
81 reflexive_impl
!(for(I
: Interner
) TyKind
<I
>);
82 reflexive_impl
!(for(I
: Interner
) LifetimeData
<I
>);
83 reflexive_impl
!(for(I
: Interner
) ConstData
<I
>);
84 reflexive_impl
!(for(I
: Interner
) TraitRef
<I
>);
85 reflexive_impl
!(for(I
: Interner
) DomainGoal
<I
>);
86 reflexive_impl
!(for(I
: Interner
) Goal
<I
>);
87 reflexive_impl
!(for(I
: Interner
) WhereClause
<I
>);
88 reflexive_impl
!(for(I
: Interner
) ProgramClause
<I
>);
89 reflexive_impl
!(for(I
: Interner
) QuantifiedWhereClause
<I
>);
90 reflexive_impl
!(for(I
: Interner
) VariableKind
<I
>);
91 reflexive_impl
!(for(I
: Interner
) VariableKinds
<I
>);
92 reflexive_impl
!(for(I
: Interner
) CanonicalVarKind
<I
>);
93 reflexive_impl
!(for(I
: Interner
) CanonicalVarKinds
<I
>);
94 reflexive_impl
!(for(I
: Interner
) Constraint
<I
>);
96 impl<I
: Interner
> CastTo
<WhereClause
<I
>> for TraitRef
<I
> {
97 fn cast_to(self, _interner
: &I
) -> WhereClause
<I
> {
98 WhereClause
::Implemented(self)
102 impl<I
: Interner
> CastTo
<WhereClause
<I
>> for AliasEq
<I
> {
103 fn cast_to(self, _interner
: &I
) -> WhereClause
<I
> {
104 WhereClause
::AliasEq(self)
108 impl<I
: Interner
> CastTo
<WhereClause
<I
>> for LifetimeOutlives
<I
> {
109 fn cast_to(self, _interner
: &I
) -> WhereClause
<I
> {
110 WhereClause
::LifetimeOutlives(self)
114 impl<T
, I
> CastTo
<DomainGoal
<I
>> for T
116 T
: CastTo
<WhereClause
<I
>>,
119 fn cast_to(self, interner
: &I
) -> DomainGoal
<I
> {
120 DomainGoal
::Holds(self.cast(interner
))
124 impl<T
, I
: Interner
> CastTo
<Goal
<I
>> for T
126 T
: CastTo
<DomainGoal
<I
>>,
128 fn cast_to(self, interner
: &I
) -> Goal
<I
> {
129 GoalData
::DomainGoal(self.cast(interner
)).intern(interner
)
133 impl<I
: Interner
> CastTo
<DomainGoal
<I
>> for Normalize
<I
> {
134 fn cast_to(self, _interner
: &I
) -> DomainGoal
<I
> {
135 DomainGoal
::Normalize(self)
139 impl<I
: Interner
> CastTo
<DomainGoal
<I
>> for WellFormed
<I
> {
140 fn cast_to(self, _interner
: &I
) -> DomainGoal
<I
> {
141 DomainGoal
::WellFormed(self)
145 impl<I
: Interner
> CastTo
<DomainGoal
<I
>> for FromEnv
<I
> {
146 fn cast_to(self, _interner
: &I
) -> DomainGoal
<I
> {
147 DomainGoal
::FromEnv(self)
151 impl<I
: Interner
> CastTo
<Goal
<I
>> for EqGoal
<I
> {
152 fn cast_to(self, interner
: &I
) -> Goal
<I
> {
153 GoalData
::EqGoal(self).intern(interner
)
157 impl<I
: Interner
> CastTo
<Goal
<I
>> for SubtypeGoal
<I
> {
158 fn cast_to(self, interner
: &I
) -> Goal
<I
> {
159 GoalData
::SubtypeGoal(self).intern(interner
)
163 impl<I
: Interner
, T
: HasInterner
<Interner
= I
> + CastTo
<Goal
<I
>>> CastTo
<Goal
<I
>> for Binders
<T
> {
164 fn cast_to(self, interner
: &I
) -> Goal
<I
> {
165 GoalData
::Quantified(
166 QuantifierKind
::ForAll
,
167 self.map(|bound
| bound
.cast(interner
)),
173 impl<I
: Interner
> CastTo
<TyKind
<I
>> for AliasTy
<I
> {
174 fn cast_to(self, _interner
: &I
) -> TyKind
<I
> {
179 impl<I
: Interner
> CastTo
<GenericArg
<I
>> for Ty
<I
> {
180 fn cast_to(self, interner
: &I
) -> GenericArg
<I
> {
181 GenericArg
::new(interner
, GenericArgData
::Ty(self))
185 impl<I
: Interner
> CastTo
<GenericArg
<I
>> for Lifetime
<I
> {
186 fn cast_to(self, interner
: &I
) -> GenericArg
<I
> {
187 GenericArg
::new(interner
, GenericArgData
::Lifetime(self))
191 impl<I
: Interner
> CastTo
<GenericArg
<I
>> for Const
<I
> {
192 fn cast_to(self, interner
: &I
) -> GenericArg
<I
> {
193 GenericArg
::new(interner
, GenericArgData
::Const(self))
197 impl<I
: Interner
> CastTo
<GenericArg
<I
>> for GenericArg
<I
> {
198 fn cast_to(self, _interner
: &I
) -> GenericArg
<I
> {
203 impl<T
, I
> CastTo
<ProgramClause
<I
>> for T
205 T
: CastTo
<DomainGoal
<I
>>,
208 fn cast_to(self, interner
: &I
) -> ProgramClause
<I
> {
209 let implication
= ProgramClauseImplication
{
210 consequence
: self.cast(interner
),
211 conditions
: Goals
::empty(interner
),
212 constraints
: Constraints
::empty(interner
),
213 priority
: ClausePriority
::High
,
216 ProgramClauseData(Binders
::empty(interner
, implication
.shifted_in(interner
)))
221 impl<I
, T
> CastTo
<ProgramClause
<I
>> for Binders
<T
>
224 T
: HasInterner
<Interner
= I
> + CastTo
<DomainGoal
<I
>>,
226 fn cast_to(self, interner
: &I
) -> ProgramClause
<I
> {
227 ProgramClauseData(self.map(|bound
| ProgramClauseImplication
{
228 consequence
: bound
.cast(interner
),
229 conditions
: Goals
::empty(interner
),
230 constraints
: Constraints
::empty(interner
),
231 priority
: ClausePriority
::High
,
237 impl<T
, U
> CastTo
<Option
<U
>> for Option
<T
>
242 fn cast_to(self, interner
: &U
::Interner
) -> Option
<U
> {
243 self.map(|v
| v
.cast(interner
))
247 impl<T
, U
, I
> CastTo
<InEnvironment
<U
>> for InEnvironment
<T
>
249 T
: HasInterner
<Interner
= I
> + CastTo
<U
>,
250 U
: HasInterner
<Interner
= I
>,
253 fn cast_to(self, interner
: &U
::Interner
) -> InEnvironment
<U
> {
254 self.map(|v
| v
.cast(interner
))
258 impl<T
, U
, E
> CastTo
<Result
<U
, E
>> for Result
<T
, E
>
263 fn cast_to(self, interner
: &U
::Interner
) -> Result
<U
, E
> {
264 self.map(|v
| v
.cast(interner
))
268 impl<T
> HasInterner
for Option
<T
>
272 type Interner
= T
::Interner
;
275 impl<T
, E
> HasInterner
for Result
<T
, E
>
279 type Interner
= T
::Interner
;
282 impl<T
, U
> CastTo
<Canonical
<U
>> for Canonical
<T
>
284 T
: CastTo
<U
> + HasInterner
,
285 U
: HasInterner
<Interner
= T
::Interner
>,
287 fn cast_to(self, interner
: &T
::Interner
) -> Canonical
<U
> {
288 // Subtle point: It should be ok to re-use the binders here,
289 // because `cast()` never introduces new inference variables,
290 // nor changes the "substance" of the type we are working
291 // with. It just introduces new wrapper types.
293 value
: self.value
.cast(interner
),
294 binders
: self.binders
.cast(interner
),
299 impl<T
, U
> CastTo
<Vec
<U
>> for Vec
<T
>
301 T
: CastTo
<U
> + HasInterner
,
304 fn cast_to(self, interner
: &U
::Interner
) -> Vec
<U
> {
305 self.into_iter().casted(interner
).collect()
309 impl<T
> CastTo
<T
> for &T
311 T
: Clone
+ HasInterner
,
313 fn cast_to(self, _interner
: &T
::Interner
) -> T
{
318 /// An iterator that casts each element to some other type.
319 pub struct Casted
<'i
, IT
, U
: HasInterner
> {
320 interner
: &'i U
::Interner
,
322 _cast
: PhantomData
<U
>,
325 impl<IT
: Iterator
, U
> Iterator
for Casted
<'_
, IT
, U
>
332 fn next(&mut self) -> Option
<Self::Item
> {
333 self.iterator
.next().map(|item
| item
.cast_to(self.interner
))
336 fn size_hint(&self) -> (usize, Option
<usize>) {
337 self.iterator
.size_hint()
341 /// An iterator adapter that casts each element we are iterating over
342 /// to some other type.
343 pub trait Caster
: Iterator
+ Sized
{
344 /// Cast each element in this iterator.
345 fn casted
<U
>(self, interner
: &U
::Interner
) -> Casted
<'_
, Self, U
>
347 Self::Item
: CastTo
<U
>,
358 impl<I
> Caster
for I
where I
: Iterator {}