|
| 1 | +use std::ops::ControlFlow; |
| 2 | + |
| 3 | +use crate::rustc_internal::Opaque; |
| 4 | + |
| 5 | +use super::ty::{ |
| 6 | + Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind, |
| 7 | + GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, |
| 8 | +}; |
| 9 | + |
| 10 | +pub trait Folder: Sized { |
| 11 | + type Break; |
| 12 | + fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> { |
| 13 | + ty.super_fold(self) |
| 14 | + } |
| 15 | + fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> { |
| 16 | + c.super_fold(self) |
| 17 | + } |
| 18 | +} |
| 19 | + |
| 20 | +pub trait Foldable: Sized + Clone { |
| 21 | + fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 22 | + self.super_fold(folder) |
| 23 | + } |
| 24 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self>; |
| 25 | +} |
| 26 | + |
| 27 | +impl Foldable for Ty { |
| 28 | + fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 29 | + folder.visit_ty(self) |
| 30 | + } |
| 31 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 32 | + let mut kind = self.kind(); |
| 33 | + match &mut kind { |
| 34 | + super::ty::TyKind::RigidTy(ty) => *ty = ty.fold(folder)?, |
| 35 | + super::ty::TyKind::Alias(_, alias) => alias.args = alias.args.fold(folder)?, |
| 36 | + super::ty::TyKind::Param(_) => {} |
| 37 | + super::ty::TyKind::Bound(_, _) => {} |
| 38 | + } |
| 39 | + ControlFlow::Continue(kind.into()) |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +impl Foldable for Const { |
| 44 | + fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 45 | + folder.fold_const(self) |
| 46 | + } |
| 47 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 48 | + let mut this = self.clone(); |
| 49 | + match &mut this.literal { |
| 50 | + super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?, |
| 51 | + super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?, |
| 52 | + super::ty::ConstantKind::Param(_) => {} |
| 53 | + } |
| 54 | + this.ty = this.ty.fold(folder)?; |
| 55 | + ControlFlow::Continue(this) |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +impl Foldable for Opaque { |
| 60 | + fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 61 | + ControlFlow::Continue(self.clone()) |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +impl Foldable for Allocation { |
| 66 | + fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 67 | + ControlFlow::Continue(self.clone()) |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +impl Foldable for UnevaluatedConst { |
| 72 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 73 | + let UnevaluatedConst { def, args, promoted } = self; |
| 74 | + ControlFlow::Continue(UnevaluatedConst { |
| 75 | + def: def.fold(folder)?, |
| 76 | + args: args.fold(folder)?, |
| 77 | + promoted: promoted.fold(folder)?, |
| 78 | + }) |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +impl Foldable for ConstDef { |
| 83 | + fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 84 | + ControlFlow::Continue(self.clone()) |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +impl<T: Foldable> Foldable for Option<T> { |
| 89 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 90 | + ControlFlow::Continue(match self { |
| 91 | + Some(val) => Some(val.fold(folder)?), |
| 92 | + None => None, |
| 93 | + }) |
| 94 | + } |
| 95 | +} |
| 96 | + |
| 97 | +impl Foldable for Promoted { |
| 98 | + fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 99 | + ControlFlow::Continue(self.clone()) |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +impl Foldable for GenericArgs { |
| 104 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 105 | + ControlFlow::Continue(GenericArgs(self.0.fold(folder)?)) |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +impl Foldable for GenericArgKind { |
| 110 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 111 | + let mut this = self.clone(); |
| 112 | + match &mut this { |
| 113 | + GenericArgKind::Lifetime(lt) => *lt = lt.fold(folder)?, |
| 114 | + GenericArgKind::Type(t) => *t = t.fold(folder)?, |
| 115 | + GenericArgKind::Const(c) => *c = c.fold(folder)?, |
| 116 | + } |
| 117 | + ControlFlow::Continue(this) |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +impl Foldable for RigidTy { |
| 122 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 123 | + let mut this = self.clone(); |
| 124 | + match &mut this { |
| 125 | + RigidTy::Bool |
| 126 | + | RigidTy::Char |
| 127 | + | RigidTy::Int(_) |
| 128 | + | RigidTy::Uint(_) |
| 129 | + | RigidTy::Float(_) |
| 130 | + | RigidTy::Never |
| 131 | + | RigidTy::Foreign(_) |
| 132 | + | RigidTy::Str => {} |
| 133 | + RigidTy::Array(t, c) => { |
| 134 | + *t = t.fold(folder)?; |
| 135 | + *c = c.fold(folder)?; |
| 136 | + } |
| 137 | + RigidTy::Slice(inner) => *inner = inner.fold(folder)?, |
| 138 | + RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?, |
| 139 | + RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?, |
| 140 | + RigidTy::FnDef(_, args) => *args = args.fold(folder)?, |
| 141 | + RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?, |
| 142 | + RigidTy::Closure(_, args) => *args = args.fold(folder)?, |
| 143 | + RigidTy::Generator(_, args, _) => *args = args.fold(folder)?, |
| 144 | + RigidTy::Dynamic(pred, r, _) => { |
| 145 | + *pred = pred.fold(folder)?; |
| 146 | + *r = r.fold(folder)?; |
| 147 | + } |
| 148 | + RigidTy::Tuple(fields) => *fields = fields.fold(folder)?, |
| 149 | + RigidTy::Adt(_, args) => *args = args.fold(folder)?, |
| 150 | + } |
| 151 | + ControlFlow::Continue(this) |
| 152 | + } |
| 153 | +} |
| 154 | + |
| 155 | +impl<T: Foldable> Foldable for Vec<T> { |
| 156 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 157 | + let mut this = self.clone(); |
| 158 | + for arg in &mut this { |
| 159 | + *arg = arg.fold(folder)?; |
| 160 | + } |
| 161 | + ControlFlow::Continue(this) |
| 162 | + } |
| 163 | +} |
| 164 | + |
| 165 | +impl<T: Foldable> Foldable for Binder<T> { |
| 166 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 167 | + ControlFlow::Continue(Self { |
| 168 | + value: self.value.fold(folder)?, |
| 169 | + bound_vars: self.bound_vars.clone(), |
| 170 | + }) |
| 171 | + } |
| 172 | +} |
| 173 | + |
| 174 | +impl Foldable for ExistentialPredicate { |
| 175 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 176 | + let mut this = self.clone(); |
| 177 | + match &mut this { |
| 178 | + ExistentialPredicate::Trait(tr) => tr.generic_args = tr.generic_args.fold(folder)?, |
| 179 | + ExistentialPredicate::Projection(p) => { |
| 180 | + p.term = p.term.fold(folder)?; |
| 181 | + p.generic_args = p.generic_args.fold(folder)?; |
| 182 | + } |
| 183 | + ExistentialPredicate::AutoTrait(_) => {} |
| 184 | + } |
| 185 | + ControlFlow::Continue(this) |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +impl Foldable for TermKind { |
| 190 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 191 | + ControlFlow::Continue(match self { |
| 192 | + TermKind::Type(t) => TermKind::Type(t.fold(folder)?), |
| 193 | + TermKind::Const(c) => TermKind::Const(c.fold(folder)?), |
| 194 | + }) |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +impl Foldable for FnSig { |
| 199 | + fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> { |
| 200 | + ControlFlow::Continue(Self { |
| 201 | + inputs_and_output: self.inputs_and_output.fold(folder)?, |
| 202 | + c_variadic: self.c_variadic, |
| 203 | + unsafety: self.unsafety, |
| 204 | + abi: self.abi.clone(), |
| 205 | + }) |
| 206 | + } |
| 207 | +} |
| 208 | + |
| 209 | +pub enum Never {} |
| 210 | + |
| 211 | +/// In order to instantiate a `Foldable`'s generic parameters with specific arguments, |
| 212 | +/// `GenericArgs` can be used as a `Folder` that replaces all mentions of generic params |
| 213 | +/// with the entries in its list. |
| 214 | +impl Folder for GenericArgs { |
| 215 | + type Break = Never; |
| 216 | + |
| 217 | + fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> { |
| 218 | + ControlFlow::Continue(match ty.kind() { |
| 219 | + TyKind::Param(p) => self[p], |
| 220 | + _ => *ty, |
| 221 | + }) |
| 222 | + } |
| 223 | + |
| 224 | + fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> { |
| 225 | + ControlFlow::Continue(match &c.literal { |
| 226 | + ConstantKind::Param(p) => self[p.clone()].clone(), |
| 227 | + _ => c.clone(), |
| 228 | + }) |
| 229 | + } |
| 230 | +} |
0 commit comments