1use crate::*;
4use std::marker::PhantomData;
5
6pub trait Cast: Sized {
43 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
53impl<T> Cast for T {}
54
55pub trait CastTo<T: HasInterner>: Sized {
60 fn cast_to(self, interner: T::Interner) -> T;
62}
63
64macro_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
81reflexive_impl!(for(I: Interner) TyKind<I>);
82reflexive_impl!(for(I: Interner) LifetimeData<I>);
83reflexive_impl!(for(I: Interner) ConstData<I>);
84reflexive_impl!(for(I: Interner) TraitRef<I>);
85reflexive_impl!(for(I: Interner) DomainGoal<I>);
86reflexive_impl!(for(I: Interner) Goal<I>);
87reflexive_impl!(for(I: Interner) WhereClause<I>);
88reflexive_impl!(for(I: Interner) ProgramClause<I>);
89reflexive_impl!(for(I: Interner) QuantifiedWhereClause<I>);
90reflexive_impl!(for(I: Interner) VariableKind<I>);
91reflexive_impl!(for(I: Interner) VariableKinds<I>);
92reflexive_impl!(for(I: Interner) CanonicalVarKind<I>);
93reflexive_impl!(for(I: Interner) CanonicalVarKinds<I>);
94reflexive_impl!(for(I: Interner) Constraint<I>);
95
96impl<I: Interner> CastTo<WhereClause<I>> for TraitRef<I> {
97 fn cast_to(self, _interner: I) -> WhereClause<I> {
98 WhereClause::Implemented(self)
99 }
100}
101
102impl<I: Interner> CastTo<WhereClause<I>> for AliasEq<I> {
103 fn cast_to(self, _interner: I) -> WhereClause<I> {
104 WhereClause::AliasEq(self)
105 }
106}
107
108impl<I: Interner> CastTo<WhereClause<I>> for LifetimeOutlives<I> {
109 fn cast_to(self, _interner: I) -> WhereClause<I> {
110 WhereClause::LifetimeOutlives(self)
111 }
112}
113
114impl<I: Interner> CastTo<WhereClause<I>> for TypeOutlives<I> {
115 fn cast_to(self, _interner: I) -> WhereClause<I> {
116 WhereClause::TypeOutlives(self)
117 }
118}
119
120impl<T, I> CastTo<DomainGoal<I>> for T
121where
122 T: CastTo<WhereClause<I>>,
123 I: Interner,
124{
125 fn cast_to(self, interner: I) -> DomainGoal<I> {
126 DomainGoal::Holds(self.cast(interner))
127 }
128}
129
130impl<T, I: Interner> CastTo<Goal<I>> for T
131where
132 T: CastTo<DomainGoal<I>>,
133{
134 fn cast_to(self, interner: I) -> Goal<I> {
135 GoalData::DomainGoal(self.cast(interner)).intern(interner)
136 }
137}
138
139impl<I: Interner> CastTo<DomainGoal<I>> for Normalize<I> {
140 fn cast_to(self, _interner: I) -> DomainGoal<I> {
141 DomainGoal::Normalize(self)
142 }
143}
144
145impl<I: Interner> CastTo<DomainGoal<I>> for WellFormed<I> {
146 fn cast_to(self, _interner: I) -> DomainGoal<I> {
147 DomainGoal::WellFormed(self)
148 }
149}
150
151impl<I: Interner> CastTo<DomainGoal<I>> for FromEnv<I> {
152 fn cast_to(self, _interner: I) -> DomainGoal<I> {
153 DomainGoal::FromEnv(self)
154 }
155}
156
157impl<I: Interner> CastTo<Goal<I>> for EqGoal<I> {
158 fn cast_to(self, interner: I) -> Goal<I> {
159 GoalData::EqGoal(self).intern(interner)
160 }
161}
162
163impl<I: Interner> CastTo<Goal<I>> for SubtypeGoal<I> {
164 fn cast_to(self, interner: I) -> Goal<I> {
165 GoalData::SubtypeGoal(self).intern(interner)
166 }
167}
168
169impl<I: Interner, T: HasInterner<Interner = I> + CastTo<Goal<I>>> CastTo<Goal<I>> for Binders<T> {
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
179impl<I: Interner> CastTo<TyKind<I>> for AliasTy<I> {
180 fn cast_to(self, _interner: I) -> TyKind<I> {
181 TyKind::Alias(self)
182 }
183}
184
185impl<I: Interner> CastTo<GenericArg<I>> for Ty<I> {
186 fn cast_to(self, interner: I) -> GenericArg<I> {
187 GenericArg::new(interner, GenericArgData::Ty(self))
188 }
189}
190
191impl<I: Interner> CastTo<GenericArg<I>> for Lifetime<I> {
192 fn cast_to(self, interner: I) -> GenericArg<I> {
193 GenericArg::new(interner, GenericArgData::Lifetime(self))
194 }
195}
196
197impl<I: Interner> CastTo<GenericArg<I>> for Const<I> {
198 fn cast_to(self, interner: I) -> GenericArg<I> {
199 GenericArg::new(interner, GenericArgData::Const(self))
200 }
201}
202
203impl<I: Interner> CastTo<GenericArg<I>> for GenericArg<I> {
204 fn cast_to(self, _interner: I) -> GenericArg<I> {
205 self
206 }
207}
208
209impl<T, I> CastTo<ProgramClause<I>> for T
210where
211 T: CastTo<DomainGoal<I>>,
212 I: Interner,
213{
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
227impl<I, T> CastTo<ProgramClause<I>> for Binders<T>
228where
229 I: Interner,
230 T: HasInterner<Interner = I> + CastTo<DomainGoal<I>>,
231{
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
243impl<T, U> CastTo<Option<U>> for Option<T>
244where
245 T: CastTo<U>,
246 U: HasInterner,
247{
248 fn cast_to(self, interner: U::Interner) -> Option<U> {
249 self.map(|v| v.cast(interner))
250 }
251}
252
253impl<T, U, I> CastTo<InEnvironment<U>> for InEnvironment<T>
254where
255 T: HasInterner<Interner = I> + CastTo<U>,
256 U: HasInterner<Interner = I>,
257 I: Interner,
258{
259 fn cast_to(self, interner: U::Interner) -> InEnvironment<U> {
260 self.map(|v| v.cast(interner))
261 }
262}
263
264impl<T, U, E> CastTo<Result<U, E>> for Result<T, E>
265where
266 T: CastTo<U>,
267 U: HasInterner,
268{
269 fn cast_to(self, interner: U::Interner) -> Result<U, E> {
270 self.map(|v| v.cast(interner))
271 }
272}
273
274impl<T> HasInterner for Option<T>
275where
276 T: HasInterner,
277{
278 type Interner = T::Interner;
279}
280
281impl<T, E> HasInterner for Result<T, E>
282where
283 T: HasInterner,
284{
285 type Interner = T::Interner;
286}
287
288impl<T, U> CastTo<Canonical<U>> for Canonical<T>
289where
290 T: CastTo<U> + HasInterner,
291 U: HasInterner<Interner = T::Interner>,
292{
293 fn cast_to(self, interner: T::Interner) -> Canonical<U> {
294 Canonical {
299 value: self.value.cast(interner),
300 binders: self.binders.cast(interner),
301 }
302 }
303}
304
305impl<T, U> CastTo<Vec<U>> for Vec<T>
306where
307 T: CastTo<U> + HasInterner,
308 U: HasInterner,
309{
310 fn cast_to(self, interner: U::Interner) -> Vec<U> {
311 self.into_iter().casted(interner).collect()
312 }
313}
314
315impl<T> CastTo<T> for &T
316where
317 T: Clone + HasInterner,
318{
319 fn cast_to(self, _interner: T::Interner) -> T {
320 self.clone()
321 }
322}
323
324pub struct Casted<IT, U: HasInterner> {
326 interner: U::Interner,
327 iterator: IT,
328 _cast: PhantomData<U>,
329}
330
331impl<IT: Iterator, U> Iterator for Casted<IT, U>
332where
333 IT::Item: CastTo<U>,
334 U: HasInterner,
335{
336 type Item = U;
337
338 fn next(&mut self) -> Option<Self::Item> {
339 self.iterator.next().map(|item| item.cast_to(self.interner))
340 }
341
342 fn size_hint(&self) -> (usize, Option<usize>) {
343 self.iterator.size_hint()
344 }
345}
346
347pub trait Caster: Iterator + Sized {
350 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
364impl<I> Caster for I where I: Iterator {}