diff options
Diffstat (limited to 'crates/hir_ty/src/walk.rs')
-rw-r--r-- | crates/hir_ty/src/walk.rs | 150 |
1 files changed, 150 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..6ef1d5336 --- /dev/null +++ b/crates/hir_ty/src/walk.rs | |||
@@ -0,0 +1,150 @@ | |||
1 | //! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and | ||
2 | //! `Visit`). | ||
3 | |||
4 | use chalk_ir::interner::HasInterner; | ||
5 | |||
6 | use crate::{ | ||
7 | AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg, GenericArgData, Interner, | ||
8 | OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, | ||
9 | }; | ||
10 | |||
11 | /// This allows walking structures that contain types to do something with those | ||
12 | /// types, similar to Chalk's `Fold` trait. | ||
13 | pub trait TypeWalk { | ||
14 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
15 | } | ||
16 | |||
17 | impl TypeWalk for Ty { | ||
18 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
19 | match self.kind(&Interner) { | ||
20 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
21 | for t in p_ty.substitution.iter(&Interner) { | ||
22 | t.walk(f); | ||
23 | } | ||
24 | } | ||
25 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
26 | for t in o_ty.substitution.iter(&Interner) { | ||
27 | t.walk(f); | ||
28 | } | ||
29 | } | ||
30 | TyKind::Dyn(dyn_ty) => { | ||
31 | for p in dyn_ty.bounds.skip_binders().interned().iter() { | ||
32 | p.walk(f); | ||
33 | } | ||
34 | } | ||
35 | TyKind::Slice(ty) | ||
36 | | TyKind::Array(ty, _) | ||
37 | | TyKind::Ref(_, _, ty) | ||
38 | | TyKind::Raw(_, ty) => { | ||
39 | ty.walk(f); | ||
40 | } | ||
41 | TyKind::Function(fn_pointer) => { | ||
42 | fn_pointer.substitution.0.walk(f); | ||
43 | } | ||
44 | TyKind::Adt(_, substs) | ||
45 | | TyKind::FnDef(_, substs) | ||
46 | | TyKind::Tuple(_, substs) | ||
47 | | TyKind::OpaqueType(_, substs) | ||
48 | | TyKind::AssociatedType(_, substs) | ||
49 | | TyKind::Closure(.., substs) => { | ||
50 | substs.walk(f); | ||
51 | } | ||
52 | _ => {} | ||
53 | } | ||
54 | f(self); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
59 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
60 | for t in self { | ||
61 | t.walk(f); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | impl TypeWalk for OpaqueTy { | ||
67 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
68 | self.substitution.walk(f); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | impl TypeWalk for ProjectionTy { | ||
73 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
74 | self.substitution.walk(f); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | impl TypeWalk for AliasTy { | ||
79 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
80 | match self { | ||
81 | AliasTy::Projection(it) => it.walk(f), | ||
82 | AliasTy::Opaque(it) => it.walk(f), | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | impl TypeWalk for GenericArg { | ||
88 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
89 | match &self.interned() { | ||
90 | GenericArgData::Ty(ty) => { | ||
91 | ty.walk(f); | ||
92 | } | ||
93 | _ => {} | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | impl TypeWalk for Substitution { | ||
99 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
100 | for t in self.iter(&Interner) { | ||
101 | t.walk(f); | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | |||
106 | impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> { | ||
107 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
108 | self.skip_binders().walk(f); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | impl TypeWalk for TraitRef { | ||
113 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
114 | self.substitution.walk(f); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | impl TypeWalk for WhereClause { | ||
119 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
120 | match self { | ||
121 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
122 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
123 | _ => {} | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl TypeWalk for CallableSig { | ||
129 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
130 | for t in self.params_and_return.iter() { | ||
131 | t.walk(f); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | impl TypeWalk for AliasEq { | ||
137 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
138 | self.ty.walk(f); | ||
139 | match &self.alias { | ||
140 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
141 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | impl TypeWalk for FnSubst<Interner> { | ||
147 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
148 | self.0.walk(f) | ||
149 | } | ||
150 | } | ||