1 //! Upcasts, to avoid writing out wrapper types.
2 
3 use crate::*;
4 use std::marker::PhantomData;
5 
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:
9 ///
10 /// ```ignore
11 /// let goal: Goal = domain_goal.cast();
12 /// ```
13 ///
14 /// This is equivalent to the more explicit:
15 ///
16 /// ```ignore
17 /// let goal: Goal = Goal::DomainGoal(domain_goal)
18 /// ```
19 ///
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).
23 ///
24 /// # Invariant
25 ///
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
30 /// that).
31 ///
32 /// # Iterators
33 ///
34 /// If you import the `Caster` trait, you can also write `.casted()` on an
35 /// iterator chain to cast every instance within.
36 ///
37 /// # Implementing Cast
38 ///
39 /// Do not implement `Cast` directly. Instead, implement `CastTo`.
40 /// This split setup allows us to write `foo.cast::<T>()` to mean
41 /// "cast to T".
42 pub trait Cast: Sized {
43     /// Cast a value to type `U` using `CastTo`.
cast<U>(self, interner: &U::Interner) -> U where Self: CastTo<U>, U: HasInterner,44     fn cast<U>(self, interner: &U::Interner) -> U
45     where
46         Self: CastTo<U>,
47         U: HasInterner,
48     {
49         self.cast_to(interner)
50     }
51 }
52 
53 impl<T> Cast for T {}
54 
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
58 /// like that.
59 pub trait CastTo<T: HasInterner>: Sized {
60     /// Cast a value to type `T`.
cast_to(self, interner: &T::Interner) -> T61     fn cast_to(self, interner: &T::Interner) -> T;
62 }
63 
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 {
68                 self
69             }
70         }
71     };
72     ($u:ty) => {
73         impl CastTo<$u> for $u {
74             fn cast_to(self, interner: &<$u as HasInterner>::Interner) -> $u {
75                 self
76             }
77         }
78     };
79 }
80 
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>);
95 
96 impl<I: Interner> CastTo<WhereClause<I>> for TraitRef<I> {
cast_to(self, _interner: &I) -> WhereClause<I>97     fn cast_to(self, _interner: &I) -> WhereClause<I> {
98         WhereClause::Implemented(self)
99     }
100 }
101 
102 impl<I: Interner> CastTo<WhereClause<I>> for AliasEq<I> {
cast_to(self, _interner: &I) -> WhereClause<I>103     fn cast_to(self, _interner: &I) -> WhereClause<I> {
104         WhereClause::AliasEq(self)
105     }
106 }
107 
108 impl<I: Interner> CastTo<WhereClause<I>> for LifetimeOutlives<I> {
cast_to(self, _interner: &I) -> WhereClause<I>109     fn cast_to(self, _interner: &I) -> WhereClause<I> {
110         WhereClause::LifetimeOutlives(self)
111     }
112 }
113 
114 impl<I: Interner> CastTo<WhereClause<I>> for TypeOutlives<I> {
cast_to(self, _interner: &I) -> WhereClause<I>115     fn cast_to(self, _interner: &I) -> WhereClause<I> {
116         WhereClause::TypeOutlives(self)
117     }
118 }
119 
120 impl<T, I> CastTo<DomainGoal<I>> for T
121 where
122     T: CastTo<WhereClause<I>>,
123     I: Interner,
124 {
cast_to(self, interner: &I) -> DomainGoal<I>125     fn cast_to(self, interner: &I) -> DomainGoal<I> {
126         DomainGoal::Holds(self.cast(interner))
127     }
128 }
129 
130 impl<T, I: Interner> CastTo<Goal<I>> for T
131 where
132     T: CastTo<DomainGoal<I>>,
133 {
cast_to(self, interner: &I) -> Goal<I>134     fn cast_to(self, interner: &I) -> Goal<I> {
135         GoalData::DomainGoal(self.cast(interner)).intern(interner)
136     }
137 }
138 
139 impl<I: Interner> CastTo<DomainGoal<I>> for Normalize<I> {
cast_to(self, _interner: &I) -> DomainGoal<I>140     fn cast_to(self, _interner: &I) -> DomainGoal<I> {
141         DomainGoal::Normalize(self)
142     }
143 }
144 
145 impl<I: Interner> CastTo<DomainGoal<I>> for WellFormed<I> {
cast_to(self, _interner: &I) -> DomainGoal<I>146     fn cast_to(self, _interner: &I) -> DomainGoal<I> {
147         DomainGoal::WellFormed(self)
148     }
149 }
150 
151 impl<I: Interner> CastTo<DomainGoal<I>> for FromEnv<I> {
cast_to(self, _interner: &I) -> DomainGoal<I>152     fn cast_to(self, _interner: &I) -> DomainGoal<I> {
153         DomainGoal::FromEnv(self)
154     }
155 }
156 
157 impl<I: Interner> CastTo<Goal<I>> for EqGoal<I> {
cast_to(self, interner: &I) -> Goal<I>158     fn cast_to(self, interner: &I) -> Goal<I> {
159         GoalData::EqGoal(self).intern(interner)
160     }
161 }
162 
163 impl<I: Interner> CastTo<Goal<I>> for SubtypeGoal<I> {
cast_to(self, interner: &I) -> Goal<I>164     fn cast_to(self, interner: &I) -> Goal<I> {
165         GoalData::SubtypeGoal(self).intern(interner)
166     }
167 }
168 
169 impl<I: Interner, T: HasInterner<Interner = I> + CastTo<Goal<I>>> CastTo<Goal<I>> for Binders<T> {
cast_to(self, interner: &I) -> Goal<I>170     fn cast_to(self, interner: &I) -> Goal<I> {
171         GoalData::Quantified(
172             QuantifierKind::ForAll,
173             self.map(|bound| bound.cast(interner)),
174         )
175         .intern(interner)
176     }
177 }
178 
179 impl<I: Interner> CastTo<TyKind<I>> for AliasTy<I> {
cast_to(self, _interner: &I) -> TyKind<I>180     fn cast_to(self, _interner: &I) -> TyKind<I> {
181         TyKind::Alias(self)
182     }
183 }
184 
185 impl<I: Interner> CastTo<GenericArg<I>> for Ty<I> {
cast_to(self, interner: &I) -> GenericArg<I>186     fn cast_to(self, interner: &I) -> GenericArg<I> {
187         GenericArg::new(interner, GenericArgData::Ty(self))
188     }
189 }
190 
191 impl<I: Interner> CastTo<GenericArg<I>> for Lifetime<I> {
cast_to(self, interner: &I) -> GenericArg<I>192     fn cast_to(self, interner: &I) -> GenericArg<I> {
193         GenericArg::new(interner, GenericArgData::Lifetime(self))
194     }
195 }
196 
197 impl<I: Interner> CastTo<GenericArg<I>> for Const<I> {
cast_to(self, interner: &I) -> GenericArg<I>198     fn cast_to(self, interner: &I) -> GenericArg<I> {
199         GenericArg::new(interner, GenericArgData::Const(self))
200     }
201 }
202 
203 impl<I: Interner> CastTo<GenericArg<I>> for GenericArg<I> {
cast_to(self, _interner: &I) -> GenericArg<I>204     fn cast_to(self, _interner: &I) -> GenericArg<I> {
205         self
206     }
207 }
208 
209 impl<T, I> CastTo<ProgramClause<I>> for T
210 where
211     T: CastTo<DomainGoal<I>>,
212     I: Interner,
213 {
cast_to(self, interner: &I) -> ProgramClause<I>214     fn cast_to(self, interner: &I) -> ProgramClause<I> {
215         let implication = ProgramClauseImplication {
216             consequence: self.cast(interner),
217             conditions: Goals::empty(interner),
218             constraints: Constraints::empty(interner),
219             priority: ClausePriority::High,
220         };
221 
222         ProgramClauseData(Binders::empty(interner, implication.shifted_in(interner)))
223             .intern(interner)
224     }
225 }
226 
227 impl<I, T> CastTo<ProgramClause<I>> for Binders<T>
228 where
229     I: Interner,
230     T: HasInterner<Interner = I> + CastTo<DomainGoal<I>>,
231 {
cast_to(self, interner: &I) -> ProgramClause<I>232     fn cast_to(self, interner: &I) -> ProgramClause<I> {
233         ProgramClauseData(self.map(|bound| ProgramClauseImplication {
234             consequence: bound.cast(interner),
235             conditions: Goals::empty(interner),
236             constraints: Constraints::empty(interner),
237             priority: ClausePriority::High,
238         }))
239         .intern(interner)
240     }
241 }
242 
243 impl<T, U> CastTo<Option<U>> for Option<T>
244 where
245     T: CastTo<U>,
246     U: HasInterner,
247 {
cast_to(self, interner: &U::Interner) -> Option<U>248     fn cast_to(self, interner: &U::Interner) -> Option<U> {
249         self.map(|v| v.cast(interner))
250     }
251 }
252 
253 impl<T, U, I> CastTo<InEnvironment<U>> for InEnvironment<T>
254 where
255     T: HasInterner<Interner = I> + CastTo<U>,
256     U: HasInterner<Interner = I>,
257     I: Interner,
258 {
cast_to(self, interner: &U::Interner) -> InEnvironment<U>259     fn cast_to(self, interner: &U::Interner) -> InEnvironment<U> {
260         self.map(|v| v.cast(interner))
261     }
262 }
263 
264 impl<T, U, E> CastTo<Result<U, E>> for Result<T, E>
265 where
266     T: CastTo<U>,
267     U: HasInterner,
268 {
cast_to(self, interner: &U::Interner) -> Result<U, E>269     fn cast_to(self, interner: &U::Interner) -> Result<U, E> {
270         self.map(|v| v.cast(interner))
271     }
272 }
273 
274 impl<T> HasInterner for Option<T>
275 where
276     T: HasInterner,
277 {
278     type Interner = T::Interner;
279 }
280 
281 impl<T, E> HasInterner for Result<T, E>
282 where
283     T: HasInterner,
284 {
285     type Interner = T::Interner;
286 }
287 
288 impl<T, U> CastTo<Canonical<U>> for Canonical<T>
289 where
290     T: CastTo<U> + HasInterner,
291     U: HasInterner<Interner = T::Interner>,
292 {
cast_to(self, interner: &T::Interner) -> Canonical<U>293     fn cast_to(self, interner: &T::Interner) -> Canonical<U> {
294         // Subtle point: It should be ok to re-use the binders here,
295         // because `cast()` never introduces new inference variables,
296         // nor changes the "substance" of the type we are working
297         // with. It just introduces new wrapper types.
298         Canonical {
299             value: self.value.cast(interner),
300             binders: self.binders.cast(interner),
301         }
302     }
303 }
304 
305 impl<T, U> CastTo<Vec<U>> for Vec<T>
306 where
307     T: CastTo<U> + HasInterner,
308     U: HasInterner,
309 {
cast_to(self, interner: &U::Interner) -> Vec<U>310     fn cast_to(self, interner: &U::Interner) -> Vec<U> {
311         self.into_iter().casted(interner).collect()
312     }
313 }
314 
315 impl<T> CastTo<T> for &T
316 where
317     T: Clone + HasInterner,
318 {
cast_to(self, _interner: &T::Interner) -> T319     fn cast_to(self, _interner: &T::Interner) -> T {
320         self.clone()
321     }
322 }
323 
324 /// An iterator that casts each element to some other type.
325 pub struct Casted<'i, IT, U: HasInterner> {
326     interner: &'i U::Interner,
327     iterator: IT,
328     _cast: PhantomData<U>,
329 }
330 
331 impl<IT: Iterator, U> Iterator for Casted<'_, IT, U>
332 where
333     IT::Item: CastTo<U>,
334     U: HasInterner,
335 {
336     type Item = U;
337 
next(&mut self) -> Option<Self::Item>338     fn next(&mut self) -> Option<Self::Item> {
339         self.iterator.next().map(|item| item.cast_to(self.interner))
340     }
341 
size_hint(&self) -> (usize, Option<usize>)342     fn size_hint(&self) -> (usize, Option<usize>) {
343         self.iterator.size_hint()
344     }
345 }
346 
347 /// An iterator adapter that casts each element we are iterating over
348 /// to some other type.
349 pub trait Caster: Iterator + Sized {
350     /// Cast each element in this iterator.
casted<U>(self, interner: &U::Interner) -> Casted<'_, Self, U> where Self::Item: CastTo<U>, U: HasInterner,351     fn casted<U>(self, interner: &U::Interner) -> Casted<'_, Self, U>
352     where
353         Self::Item: CastTo<U>,
354         U: HasInterner,
355     {
356         Casted {
357             interner,
358             iterator: self,
359             _cast: PhantomData,
360         }
361     }
362 }
363 
364 impl<I> Caster for I where I: Iterator {}
365