aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/walk.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/walk.rs')
-rw-r--r--crates/hir_ty/src/walk.rs150
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
4use chalk_ir::interner::HasInterner;
5
6use 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.
13pub trait TypeWalk {
14 fn walk(&self, f: &mut impl FnMut(&Ty));
15}
16
17impl 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
58impl<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
66impl TypeWalk for OpaqueTy {
67 fn walk(&self, f: &mut impl FnMut(&Ty)) {
68 self.substitution.walk(f);
69 }
70}
71
72impl TypeWalk for ProjectionTy {
73 fn walk(&self, f: &mut impl FnMut(&Ty)) {
74 self.substitution.walk(f);
75 }
76}
77
78impl 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
87impl 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
98impl 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
106impl<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
112impl TypeWalk for TraitRef {
113 fn walk(&self, f: &mut impl FnMut(&Ty)) {
114 self.substitution.walk(f);
115 }
116}
117
118impl 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
128impl 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
136impl 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
146impl TypeWalk for FnSubst<Interner> {
147 fn walk(&self, f: &mut impl FnMut(&Ty)) {
148 self.0.walk(f)
149 }
150}