]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir-0.55.0/src/cast.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / vendor / chalk-ir-0.55.0 / src / cast.rs
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`.
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`.
61 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> {
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> {
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> {
109 fn cast_to(self, _interner: &I) -> WhereClause<I> {
110 WhereClause::LifetimeOutlives(self)
111 }
112 }
113
114 impl<T, I> CastTo<DomainGoal<I>> for T
115 where
116 T: CastTo<WhereClause<I>>,
117 I: Interner,
118 {
119 fn cast_to(self, interner: &I) -> DomainGoal<I> {
120 DomainGoal::Holds(self.cast(interner))
121 }
122 }
123
124 impl<T, I: Interner> CastTo<Goal<I>> for T
125 where
126 T: CastTo<DomainGoal<I>>,
127 {
128 fn cast_to(self, interner: &I) -> Goal<I> {
129 GoalData::DomainGoal(self.cast(interner)).intern(interner)
130 }
131 }
132
133 impl<I: Interner> CastTo<DomainGoal<I>> for Normalize<I> {
134 fn cast_to(self, _interner: &I) -> DomainGoal<I> {
135 DomainGoal::Normalize(self)
136 }
137 }
138
139 impl<I: Interner> CastTo<DomainGoal<I>> for WellFormed<I> {
140 fn cast_to(self, _interner: &I) -> DomainGoal<I> {
141 DomainGoal::WellFormed(self)
142 }
143 }
144
145 impl<I: Interner> CastTo<DomainGoal<I>> for FromEnv<I> {
146 fn cast_to(self, _interner: &I) -> DomainGoal<I> {
147 DomainGoal::FromEnv(self)
148 }
149 }
150
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)
154 }
155 }
156
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)
160 }
161 }
162
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)),
168 )
169 .intern(interner)
170 }
171 }
172
173 impl<I: Interner> CastTo<TyKind<I>> for AliasTy<I> {
174 fn cast_to(self, _interner: &I) -> TyKind<I> {
175 TyKind::Alias(self)
176 }
177 }
178
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))
182 }
183 }
184
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))
188 }
189 }
190
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))
194 }
195 }
196
197 impl<I: Interner> CastTo<GenericArg<I>> for GenericArg<I> {
198 fn cast_to(self, _interner: &I) -> GenericArg<I> {
199 self
200 }
201 }
202
203 impl<T, I> CastTo<ProgramClause<I>> for T
204 where
205 T: CastTo<DomainGoal<I>>,
206 I: Interner,
207 {
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,
214 };
215
216 ProgramClauseData(Binders::empty(interner, implication.shifted_in(interner)))
217 .intern(interner)
218 }
219 }
220
221 impl<I, T> CastTo<ProgramClause<I>> for Binders<T>
222 where
223 I: Interner,
224 T: HasInterner<Interner = I> + CastTo<DomainGoal<I>>,
225 {
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,
232 }))
233 .intern(interner)
234 }
235 }
236
237 impl<T, U> CastTo<Option<U>> for Option<T>
238 where
239 T: CastTo<U>,
240 U: HasInterner,
241 {
242 fn cast_to(self, interner: &U::Interner) -> Option<U> {
243 self.map(|v| v.cast(interner))
244 }
245 }
246
247 impl<T, U, I> CastTo<InEnvironment<U>> for InEnvironment<T>
248 where
249 T: HasInterner<Interner = I> + CastTo<U>,
250 U: HasInterner<Interner = I>,
251 I: Interner,
252 {
253 fn cast_to(self, interner: &U::Interner) -> InEnvironment<U> {
254 self.map(|v| v.cast(interner))
255 }
256 }
257
258 impl<T, U, E> CastTo<Result<U, E>> for Result<T, E>
259 where
260 T: CastTo<U>,
261 U: HasInterner,
262 {
263 fn cast_to(self, interner: &U::Interner) -> Result<U, E> {
264 self.map(|v| v.cast(interner))
265 }
266 }
267
268 impl<T> HasInterner for Option<T>
269 where
270 T: HasInterner,
271 {
272 type Interner = T::Interner;
273 }
274
275 impl<T, E> HasInterner for Result<T, E>
276 where
277 T: HasInterner,
278 {
279 type Interner = T::Interner;
280 }
281
282 impl<T, U> CastTo<Canonical<U>> for Canonical<T>
283 where
284 T: CastTo<U> + HasInterner,
285 U: HasInterner<Interner = T::Interner>,
286 {
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.
292 Canonical {
293 value: self.value.cast(interner),
294 binders: self.binders.cast(interner),
295 }
296 }
297 }
298
299 impl<T, U> CastTo<Vec<U>> for Vec<T>
300 where
301 T: CastTo<U> + HasInterner,
302 U: HasInterner,
303 {
304 fn cast_to(self, interner: &U::Interner) -> Vec<U> {
305 self.into_iter().casted(interner).collect()
306 }
307 }
308
309 impl<T> CastTo<T> for &T
310 where
311 T: Clone + HasInterner,
312 {
313 fn cast_to(self, _interner: &T::Interner) -> T {
314 self.clone()
315 }
316 }
317
318 /// An iterator that casts each element to some other type.
319 pub struct Casted<'i, IT, U: HasInterner> {
320 interner: &'i U::Interner,
321 iterator: IT,
322 _cast: PhantomData<U>,
323 }
324
325 impl<IT: Iterator, U> Iterator for Casted<'_, IT, U>
326 where
327 IT::Item: CastTo<U>,
328 U: HasInterner,
329 {
330 type Item = U;
331
332 fn next(&mut self) -> Option<Self::Item> {
333 self.iterator.next().map(|item| item.cast_to(self.interner))
334 }
335
336 fn size_hint(&self) -> (usize, Option<usize>) {
337 self.iterator.size_hint()
338 }
339 }
340
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>
346 where
347 Self::Item: CastTo<U>,
348 U: HasInterner,
349 {
350 Casted {
351 interner,
352 iterator: self,
353 _cast: PhantomData,
354 }
355 }
356 }
357
358 impl<I> Caster for I where I: Iterator {}