diff options
author | Florian Diebold <[email protected]> | 2021-04-04 19:22:00 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-04-04 19:22:00 +0100 |
commit | 508a1ecad3cf9c9f01022b3e95f9d6a7ad7a4cd5 (patch) | |
tree | 88f6dd30f03815c04054bb50e302dcd92c8d09c9 /crates/hir_ty/src/walk.rs | |
parent | bc8b27884132a4dbfa019f7d3d5fcbbf9f4912af (diff) |
Move things in hir_ty into submodules
- all the types that will be replaced by Chalk go to `types`
- `TypeWalk` impls go to `walk`
Diffstat (limited to 'crates/hir_ty/src/walk.rs')
-rw-r--r-- | crates/hir_ty/src/walk.rs | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs new file mode 100644 index 000000000..fec5c2f42 --- /dev/null +++ b/crates/hir_ty/src/walk.rs | |||
@@ -0,0 +1,359 @@ | |||
1 | //! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and | ||
2 | //! `Visit`). | ||
3 | |||
4 | use std::mem; | ||
5 | |||
6 | use chalk_ir::DebruijnIndex; | ||
7 | |||
8 | use crate::{ | ||
9 | utils::make_mut_slice, AliasTy, Binders, CallableSig, GenericArg, GenericArgData, Interner, | ||
10 | OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, | ||
11 | }; | ||
12 | |||
13 | /// This allows walking structures that contain types to do something with those | ||
14 | /// types, similar to Chalk's `Fold` trait. | ||
15 | pub trait TypeWalk { | ||
16 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
17 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
18 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
19 | } | ||
20 | /// Walk the type, counting entered binders. | ||
21 | /// | ||
22 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
23 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
24 | /// substitute a certain bound variable, we can't just walk the whole type | ||
25 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
26 | /// things that introduce new bound variables, we have to keep track of | ||
27 | /// that. Currently, the only thing that introduces bound variables on our | ||
28 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
29 | /// variable for the self type. | ||
30 | fn walk_mut_binders( | ||
31 | &mut self, | ||
32 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
33 | binders: DebruijnIndex, | ||
34 | ); | ||
35 | |||
36 | fn fold_binders( | ||
37 | mut self, | ||
38 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
39 | binders: DebruijnIndex, | ||
40 | ) -> Self | ||
41 | where | ||
42 | Self: Sized, | ||
43 | { | ||
44 | self.walk_mut_binders( | ||
45 | &mut |ty_mut, binders| { | ||
46 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
47 | *ty_mut = f(ty, binders); | ||
48 | }, | ||
49 | binders, | ||
50 | ); | ||
51 | self | ||
52 | } | ||
53 | |||
54 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
55 | where | ||
56 | Self: Sized, | ||
57 | { | ||
58 | self.walk_mut(&mut |ty_mut| { | ||
59 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
60 | *ty_mut = f(ty); | ||
61 | }); | ||
62 | self | ||
63 | } | ||
64 | |||
65 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
66 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
67 | where | ||
68 | Self: Sized, | ||
69 | { | ||
70 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
71 | } | ||
72 | |||
73 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
74 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
75 | where | ||
76 | Self: Sized, | ||
77 | { | ||
78 | self.walk_mut_binders( | ||
79 | &mut |ty, binders| { | ||
80 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
81 | if bound.debruijn >= binders { | ||
82 | *ty = substs.interned()[bound.index] | ||
83 | .assert_ty_ref(&Interner) | ||
84 | .clone() | ||
85 | .shift_bound_vars(binders); | ||
86 | } | ||
87 | } | ||
88 | }, | ||
89 | depth, | ||
90 | ); | ||
91 | self | ||
92 | } | ||
93 | |||
94 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
95 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
96 | where | ||
97 | Self: Sized, | ||
98 | { | ||
99 | self.fold_binders( | ||
100 | &mut |ty, binders| match ty.kind(&Interner) { | ||
101 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
102 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
103 | } | ||
104 | _ => ty, | ||
105 | }, | ||
106 | DebruijnIndex::INNERMOST, | ||
107 | ) | ||
108 | } | ||
109 | |||
110 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
111 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
112 | where | ||
113 | Self: Sized + std::fmt::Debug, | ||
114 | { | ||
115 | self.fold_binders( | ||
116 | &mut |ty, binders| match ty.kind(&Interner) { | ||
117 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
118 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
119 | .intern(&Interner) | ||
120 | } | ||
121 | _ => ty, | ||
122 | }, | ||
123 | DebruijnIndex::INNERMOST, | ||
124 | ) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl TypeWalk for Ty { | ||
129 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
130 | match self.kind(&Interner) { | ||
131 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
132 | for t in p_ty.substitution.iter(&Interner) { | ||
133 | t.walk(f); | ||
134 | } | ||
135 | } | ||
136 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
137 | for t in o_ty.substitution.iter(&Interner) { | ||
138 | t.walk(f); | ||
139 | } | ||
140 | } | ||
141 | TyKind::Dyn(dyn_ty) => { | ||
142 | for p in dyn_ty.bounds.value.interned().iter() { | ||
143 | p.walk(f); | ||
144 | } | ||
145 | } | ||
146 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
147 | ty.walk(f); | ||
148 | } | ||
149 | _ => { | ||
150 | if let Some(substs) = self.substs() { | ||
151 | for t in substs.iter(&Interner) { | ||
152 | t.walk(f); | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | f(self); | ||
158 | } | ||
159 | |||
160 | fn walk_mut_binders( | ||
161 | &mut self, | ||
162 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
163 | binders: DebruijnIndex, | ||
164 | ) { | ||
165 | match self.interned_mut() { | ||
166 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
167 | p_ty.substitution.walk_mut_binders(f, binders); | ||
168 | } | ||
169 | TyKind::Dyn(dyn_ty) => { | ||
170 | for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { | ||
171 | p.walk_mut_binders(f, binders.shifted_in()); | ||
172 | } | ||
173 | } | ||
174 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
175 | o_ty.substitution.walk_mut_binders(f, binders); | ||
176 | } | ||
177 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
178 | ty.walk_mut_binders(f, binders); | ||
179 | } | ||
180 | _ => { | ||
181 | if let Some(substs) = self.substs_mut() { | ||
182 | substs.walk_mut_binders(f, binders); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | f(self, binders); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
191 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
192 | for t in self { | ||
193 | t.walk(f); | ||
194 | } | ||
195 | } | ||
196 | fn walk_mut_binders( | ||
197 | &mut self, | ||
198 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
199 | binders: DebruijnIndex, | ||
200 | ) { | ||
201 | for t in self { | ||
202 | t.walk_mut_binders(f, binders); | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl TypeWalk for OpaqueTy { | ||
208 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
209 | self.substitution.walk(f); | ||
210 | } | ||
211 | |||
212 | fn walk_mut_binders( | ||
213 | &mut self, | ||
214 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
215 | binders: DebruijnIndex, | ||
216 | ) { | ||
217 | self.substitution.walk_mut_binders(f, binders); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | impl TypeWalk for ProjectionTy { | ||
222 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
223 | self.substitution.walk(f); | ||
224 | } | ||
225 | |||
226 | fn walk_mut_binders( | ||
227 | &mut self, | ||
228 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
229 | binders: DebruijnIndex, | ||
230 | ) { | ||
231 | self.substitution.walk_mut_binders(f, binders); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | impl TypeWalk for AliasTy { | ||
236 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
237 | match self { | ||
238 | AliasTy::Projection(it) => it.walk(f), | ||
239 | AliasTy::Opaque(it) => it.walk(f), | ||
240 | } | ||
241 | } | ||
242 | |||
243 | fn walk_mut_binders( | ||
244 | &mut self, | ||
245 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
246 | binders: DebruijnIndex, | ||
247 | ) { | ||
248 | match self { | ||
249 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
250 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | impl TypeWalk for GenericArg { | ||
256 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
257 | match &self.interned() { | ||
258 | GenericArgData::Ty(ty) => { | ||
259 | ty.walk(f); | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn walk_mut_binders( | ||
265 | &mut self, | ||
266 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
267 | binders: DebruijnIndex, | ||
268 | ) { | ||
269 | match self.interned_mut() { | ||
270 | GenericArgData::Ty(ty) => { | ||
271 | ty.walk_mut_binders(f, binders); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | impl TypeWalk for Substitution { | ||
278 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
279 | for t in self.iter(&Interner) { | ||
280 | t.walk(f); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | fn walk_mut_binders( | ||
285 | &mut self, | ||
286 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
287 | binders: DebruijnIndex, | ||
288 | ) { | ||
289 | for t in self.interned_mut() { | ||
290 | t.walk_mut_binders(f, binders); | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
296 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
297 | self.value.walk(f); | ||
298 | } | ||
299 | |||
300 | fn walk_mut_binders( | ||
301 | &mut self, | ||
302 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
303 | binders: DebruijnIndex, | ||
304 | ) { | ||
305 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
306 | } | ||
307 | } | ||
308 | |||
309 | impl TypeWalk for TraitRef { | ||
310 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
311 | self.substitution.walk(f); | ||
312 | } | ||
313 | |||
314 | fn walk_mut_binders( | ||
315 | &mut self, | ||
316 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
317 | binders: DebruijnIndex, | ||
318 | ) { | ||
319 | self.substitution.walk_mut_binders(f, binders); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | impl TypeWalk for WhereClause { | ||
324 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
325 | match self { | ||
326 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
327 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
328 | } | ||
329 | } | ||
330 | |||
331 | fn walk_mut_binders( | ||
332 | &mut self, | ||
333 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
334 | binders: DebruijnIndex, | ||
335 | ) { | ||
336 | match self { | ||
337 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
338 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | impl TypeWalk for CallableSig { | ||
344 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
345 | for t in self.params_and_return.iter() { | ||
346 | t.walk(f); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | fn walk_mut_binders( | ||
351 | &mut self, | ||
352 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
353 | binders: DebruijnIndex, | ||
354 | ) { | ||
355 | for t in make_mut_slice(&mut self.params_and_return) { | ||
356 | t.walk_mut_binders(f, binders); | ||
357 | } | ||
358 | } | ||
359 | } | ||