1 //! `TypeFoldable` implementations for MIR types
5 use rustc_data_structures::functor::IdFunctor;
7 TrivialTypeFoldableAndLiftImpls! {
15 UserTypeAnnotationIndex,
18 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
19 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
20 use crate::mir::TerminatorKind::*;
22 let kind = match self.kind {
23 Goto { target } => Goto { target },
24 SwitchInt { discr, switch_ty, targets } => SwitchInt {
25 discr: discr.fold_with(folder)?,
26 switch_ty: switch_ty.fold_with(folder)?,
29 Drop { place, target, unwind } => {
30 Drop { place: place.fold_with(folder)?, target, unwind }
32 DropAndReplace { place, value, target, unwind } => DropAndReplace {
33 place: place.fold_with(folder)?,
34 value: value.fold_with(folder)?,
38 Yield { value, resume, resume_arg, drop } => Yield {
39 value: value.fold_with(folder)?,
41 resume_arg: resume_arg.fold_with(folder)?,
44 Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
45 let dest = destination
46 .map(|(loc, dest)| (loc.fold_with(folder).map(|loc| (loc, dest))))
50 func: func.fold_with(folder)?,
51 args: args.fold_with(folder)?,
58 Assert { cond, expected, msg, target, cleanup } => {
61 BoundsCheck { len, index } => {
62 BoundsCheck { len: len.fold_with(folder)?, index: index.fold_with(folder)? }
64 Overflow(op, l, r) => Overflow(op, l.fold_with(folder)?, r.fold_with(folder)?),
65 OverflowNeg(op) => OverflowNeg(op.fold_with(folder)?),
66 DivisionByZero(op) => DivisionByZero(op.fold_with(folder)?),
67 RemainderByZero(op) => RemainderByZero(op.fold_with(folder)?),
68 ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
70 Assert { cond: cond.fold_with(folder)?, expected, msg, target, cleanup }
72 GeneratorDrop => GeneratorDrop,
76 Unreachable => Unreachable,
77 FalseEdge { real_target, imaginary_target } => {
78 FalseEdge { real_target, imaginary_target }
80 FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
81 InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
83 operands: operands.fold_with(folder)?,
89 Ok(Terminator { source_info: self.source_info, kind })
92 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
93 use crate::mir::TerminatorKind::*;
96 SwitchInt { ref discr, switch_ty, .. } => {
97 discr.visit_with(visitor)?;
98 switch_ty.visit_with(visitor)
100 Drop { ref place, .. } => place.visit_with(visitor),
101 DropAndReplace { ref place, ref value, .. } => {
102 place.visit_with(visitor)?;
103 value.visit_with(visitor)
105 Yield { ref value, .. } => value.visit_with(visitor),
106 Call { ref func, ref args, ref destination, .. } => {
107 if let Some((ref loc, _)) = *destination {
108 loc.visit_with(visitor)?;
110 func.visit_with(visitor)?;
111 args.visit_with(visitor)
113 Assert { ref cond, ref msg, .. } => {
114 cond.visit_with(visitor)?;
117 BoundsCheck { ref len, ref index } => {
118 len.visit_with(visitor)?;
119 index.visit_with(visitor)
121 Overflow(_, l, r) => {
122 l.visit_with(visitor)?;
123 r.visit_with(visitor)
125 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
126 op.visit_with(visitor)
128 ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
131 InlineAsm { ref operands, .. } => operands.visit_with(visitor),
139 | FalseUnwind { .. } => ControlFlow::CONTINUE,
144 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
145 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
149 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
150 ControlFlow::CONTINUE
154 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
155 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
157 local: self.local.fold_with(folder)?,
158 projection: self.projection.fold_with(folder)?,
162 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
163 self.local.visit_with(visitor)?;
164 self.projection.visit_with(visitor)
168 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
169 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
170 ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
173 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
174 self.iter().try_for_each(|t| t.visit_with(visitor))
178 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
179 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
180 use crate::mir::Rvalue::*;
182 Use(op) => Use(op.fold_with(folder)?),
183 Repeat(op, len) => Repeat(op.fold_with(folder)?, len.fold_with(folder)?),
184 ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)?),
185 Ref(region, bk, place) => Ref(region.fold_with(folder)?, bk, place.fold_with(folder)?),
186 AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)?),
187 Len(place) => Len(place.fold_with(folder)?),
188 Cast(kind, op, ty) => Cast(kind, op.fold_with(folder)?, ty.fold_with(folder)?),
189 BinaryOp(op, box (rhs, lhs)) => {
190 BinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?)))
192 CheckedBinaryOp(op, box (rhs, lhs)) => {
193 CheckedBinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?)))
195 UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)?),
196 Discriminant(place) => Discriminant(place.fold_with(folder)?),
197 NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)?),
198 Aggregate(kind, fields) => {
199 let kind = kind.try_map_id(|kind| {
201 AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?),
202 AggregateKind::Tuple => AggregateKind::Tuple,
203 AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
206 substs.fold_with(folder)?,
207 user_ty.fold_with(folder)?,
210 AggregateKind::Closure(id, substs) => {
211 AggregateKind::Closure(id, substs.fold_with(folder)?)
213 AggregateKind::Generator(id, substs, movablity) => {
214 AggregateKind::Generator(id, substs.fold_with(folder)?, movablity)
218 Aggregate(kind, fields.fold_with(folder)?)
220 ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder)?, ty.fold_with(folder)?),
224 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
225 use crate::mir::Rvalue::*;
227 Use(ref op) => op.visit_with(visitor),
228 Repeat(ref op, _) => op.visit_with(visitor),
229 ThreadLocalRef(did) => did.visit_with(visitor),
230 Ref(region, _, ref place) => {
231 region.visit_with(visitor)?;
232 place.visit_with(visitor)
234 AddressOf(_, ref place) => place.visit_with(visitor),
235 Len(ref place) => place.visit_with(visitor),
236 Cast(_, ref op, ty) => {
237 op.visit_with(visitor)?;
238 ty.visit_with(visitor)
240 BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
241 rhs.visit_with(visitor)?;
242 lhs.visit_with(visitor)
244 UnaryOp(_, ref val) => val.visit_with(visitor),
245 Discriminant(ref place) => place.visit_with(visitor),
246 NullaryOp(_, ty) => ty.visit_with(visitor),
247 Aggregate(ref kind, ref fields) => {
249 AggregateKind::Array(ty) => {
250 ty.visit_with(visitor)?;
252 AggregateKind::Tuple => {}
253 AggregateKind::Adt(_, _, substs, user_ty, _) => {
254 substs.visit_with(visitor)?;
255 user_ty.visit_with(visitor)?;
257 AggregateKind::Closure(_, substs) => {
258 substs.visit_with(visitor)?;
260 AggregateKind::Generator(_, substs, _) => {
261 substs.visit_with(visitor)?;
264 fields.visit_with(visitor)
266 ShallowInitBox(ref op, ty) => {
267 op.visit_with(visitor)?;
268 ty.visit_with(visitor)
274 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
275 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
277 Operand::Copy(place) => Operand::Copy(place.fold_with(folder)?),
278 Operand::Move(place) => Operand::Move(place.fold_with(folder)?),
279 Operand::Constant(c) => Operand::Constant(c.fold_with(folder)?),
283 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
285 Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
286 Operand::Constant(ref c) => c.visit_with(visitor),
291 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
292 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
293 use crate::mir::ProjectionElem::*;
297 Field(f, ty) => Field(f, ty.fold_with(folder)?),
298 Index(v) => Index(v.fold_with(folder)?),
299 Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
300 ConstantIndex { offset, min_length, from_end } => {
301 ConstantIndex { offset, min_length, from_end }
303 Subslice { from, to, from_end } => Subslice { from, to, from_end },
307 fn super_visit_with<Vs: TypeVisitor<'tcx>>(
310 ) -> ControlFlow<Vs::BreakTy> {
311 use crate::mir::ProjectionElem::*;
314 Field(_, ty) => ty.visit_with(visitor),
315 Index(v) => v.visit_with(visitor),
316 _ => ControlFlow::CONTINUE,
321 impl<'tcx> TypeFoldable<'tcx> for Field {
322 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
325 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
326 ControlFlow::CONTINUE
330 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
331 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
334 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
335 ControlFlow::CONTINUE
339 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
340 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
343 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
344 ControlFlow::CONTINUE
348 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
349 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
352 user_ty: self.user_ty.fold_with(folder)?,
353 literal: self.literal.fold_with(folder)?,
356 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
357 self.literal.visit_with(visitor)?;
358 self.user_ty.visit_with(visitor)
362 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
364 fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
365 folder.fold_mir_const(self)
368 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
370 ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)),
371 ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.fold_with(folder)?)),
375 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
377 ConstantKind::Ty(c) => c.visit_with(visitor),
378 ConstantKind::Val(_, t) => t.visit_with(visitor),