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 { walk(&self, f: &mut impl FnMut(&Ty))14 fn walk(&self, f: &mut impl FnMut(&Ty)); 15 } 16 17 impl TypeWalk for Ty { walk(&self, f: &mut impl FnMut(&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> { walk(&self, f: &mut impl FnMut(&Ty))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 { walk(&self, f: &mut impl FnMut(&Ty))67 fn walk(&self, f: &mut impl FnMut(&Ty)) { 68 self.substitution.walk(f); 69 } 70 } 71 72 impl TypeWalk for ProjectionTy { walk(&self, f: &mut impl FnMut(&Ty))73 fn walk(&self, f: &mut impl FnMut(&Ty)) { 74 self.substitution.walk(f); 75 } 76 } 77 78 impl TypeWalk for AliasTy { walk(&self, f: &mut impl FnMut(&Ty))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 { walk(&self, f: &mut impl FnMut(&Ty))88 fn walk(&self, f: &mut impl FnMut(&Ty)) { 89 if let GenericArgData::Ty(ty) = &self.interned() { 90 ty.walk(f); 91 } 92 } 93 } 94 95 impl TypeWalk for Substitution { walk(&self, f: &mut impl FnMut(&Ty))96 fn walk(&self, f: &mut impl FnMut(&Ty)) { 97 for t in self.iter(Interner) { 98 t.walk(f); 99 } 100 } 101 } 102 103 impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> { walk(&self, f: &mut impl FnMut(&Ty))104 fn walk(&self, f: &mut impl FnMut(&Ty)) { 105 self.skip_binders().walk(f); 106 } 107 } 108 109 impl TypeWalk for TraitRef { walk(&self, f: &mut impl FnMut(&Ty))110 fn walk(&self, f: &mut impl FnMut(&Ty)) { 111 self.substitution.walk(f); 112 } 113 } 114 115 impl TypeWalk for WhereClause { walk(&self, f: &mut impl FnMut(&Ty))116 fn walk(&self, f: &mut impl FnMut(&Ty)) { 117 match self { 118 WhereClause::Implemented(trait_ref) => trait_ref.walk(f), 119 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), 120 _ => {} 121 } 122 } 123 } 124 125 impl TypeWalk for CallableSig { walk(&self, f: &mut impl FnMut(&Ty))126 fn walk(&self, f: &mut impl FnMut(&Ty)) { 127 for t in self.params_and_return.iter() { 128 t.walk(f); 129 } 130 } 131 } 132 133 impl TypeWalk for AliasEq { walk(&self, f: &mut impl FnMut(&Ty))134 fn walk(&self, f: &mut impl FnMut(&Ty)) { 135 self.ty.walk(f); 136 match &self.alias { 137 AliasTy::Projection(projection_ty) => projection_ty.walk(f), 138 AliasTy::Opaque(opaque) => opaque.walk(f), 139 } 140 } 141 } 142 143 impl TypeWalk for FnSubst<Interner> { walk(&self, f: &mut impl FnMut(&Ty))144 fn walk(&self, f: &mut impl FnMut(&Ty)) { 145 self.0.walk(f) 146 } 147 } 148