]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/walk.rs
clippy::redundant_closure
[rust.git] / crates / hir_ty / src / walk.rs
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 }