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 try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
22 ) -> Result<Self, F::Error> {
23 use crate::mir::TerminatorKind::*;
25 let kind = match self.kind {
26 Goto { target } => Goto { target },
27 SwitchInt { discr, switch_ty, targets } => SwitchInt {
28 discr: discr.try_fold_with(folder)?,
29 switch_ty: switch_ty.try_fold_with(folder)?,
32 Drop { place, target, unwind } => {
33 Drop { place: place.try_fold_with(folder)?, target, unwind }
35 DropAndReplace { place, value, target, unwind } => DropAndReplace {
36 place: place.try_fold_with(folder)?,
37 value: value.try_fold_with(folder)?,
41 Yield { value, resume, resume_arg, drop } => Yield {
42 value: value.try_fold_with(folder)?,
44 resume_arg: resume_arg.try_fold_with(folder)?,
47 Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
48 let dest = destination
49 .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest))))
53 func: func.try_fold_with(folder)?,
54 args: args.try_fold_with(folder)?,
61 Assert { cond, expected, msg, target, cleanup } => {
64 BoundsCheck { len, index } => BoundsCheck {
65 len: len.try_fold_with(folder)?,
66 index: index.try_fold_with(folder)?,
68 Overflow(op, l, r) => {
69 Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?)
71 OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?),
72 DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?),
73 RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?),
74 ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
76 Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup }
78 GeneratorDrop => GeneratorDrop,
82 Unreachable => Unreachable,
83 FalseEdge { real_target, imaginary_target } => {
84 FalseEdge { real_target, imaginary_target }
86 FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
87 InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
89 operands: operands.try_fold_with(folder)?,
95 Ok(Terminator { source_info: self.source_info, kind })
98 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
99 use crate::mir::TerminatorKind::*;
102 SwitchInt { ref discr, switch_ty, .. } => {
103 discr.visit_with(visitor)?;
104 switch_ty.visit_with(visitor)
106 Drop { ref place, .. } => place.visit_with(visitor),
107 DropAndReplace { ref place, ref value, .. } => {
108 place.visit_with(visitor)?;
109 value.visit_with(visitor)
111 Yield { ref value, .. } => value.visit_with(visitor),
112 Call { ref func, ref args, ref destination, .. } => {
113 if let Some((ref loc, _)) = *destination {
114 loc.visit_with(visitor)?;
116 func.visit_with(visitor)?;
117 args.visit_with(visitor)
119 Assert { ref cond, ref msg, .. } => {
120 cond.visit_with(visitor)?;
123 BoundsCheck { ref len, ref index } => {
124 len.visit_with(visitor)?;
125 index.visit_with(visitor)
127 Overflow(_, l, r) => {
128 l.visit_with(visitor)?;
129 r.visit_with(visitor)
131 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
132 op.visit_with(visitor)
134 ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
137 InlineAsm { ref operands, .. } => operands.visit_with(visitor),
145 | FalseUnwind { .. } => ControlFlow::CONTINUE,
150 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
151 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
155 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
156 ControlFlow::CONTINUE
160 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
161 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
164 ) -> Result<Self, F::Error> {
166 local: self.local.try_fold_with(folder)?,
167 projection: self.projection.try_fold_with(folder)?,
171 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
172 self.local.visit_with(visitor)?;
173 self.projection.visit_with(visitor)
177 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
178 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
181 ) -> Result<Self, F::Error> {
182 ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
185 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
186 self.iter().try_for_each(|t| t.visit_with(visitor))
190 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
191 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
194 ) -> Result<Self, F::Error> {
195 use crate::mir::Rvalue::*;
197 Use(op) => Use(op.try_fold_with(folder)?),
198 Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?),
199 ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?),
200 Ref(region, bk, place) => {
201 Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?)
203 AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?),
204 Len(place) => Len(place.try_fold_with(folder)?),
205 Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?),
206 BinaryOp(op, box (rhs, lhs)) => {
207 BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)))
209 CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp(
211 Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)),
213 UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?),
214 Discriminant(place) => Discriminant(place.try_fold_with(folder)?),
215 NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?),
216 Aggregate(kind, fields) => {
217 let kind = kind.try_map_id(|kind| {
219 AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?),
220 AggregateKind::Tuple => AggregateKind::Tuple,
221 AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
224 substs.try_fold_with(folder)?,
225 user_ty.try_fold_with(folder)?,
228 AggregateKind::Closure(id, substs) => {
229 AggregateKind::Closure(id, substs.try_fold_with(folder)?)
231 AggregateKind::Generator(id, substs, movablity) => {
232 AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
236 Aggregate(kind, fields.try_fold_with(folder)?)
238 ShallowInitBox(op, ty) => {
239 ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
244 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
245 use crate::mir::Rvalue::*;
247 Use(ref op) => op.visit_with(visitor),
248 Repeat(ref op, _) => op.visit_with(visitor),
249 ThreadLocalRef(did) => did.visit_with(visitor),
250 Ref(region, _, ref place) => {
251 region.visit_with(visitor)?;
252 place.visit_with(visitor)
254 AddressOf(_, ref place) => place.visit_with(visitor),
255 Len(ref place) => place.visit_with(visitor),
256 Cast(_, ref op, ty) => {
257 op.visit_with(visitor)?;
258 ty.visit_with(visitor)
260 BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
261 rhs.visit_with(visitor)?;
262 lhs.visit_with(visitor)
264 UnaryOp(_, ref val) => val.visit_with(visitor),
265 Discriminant(ref place) => place.visit_with(visitor),
266 NullaryOp(_, ty) => ty.visit_with(visitor),
267 Aggregate(ref kind, ref fields) => {
269 AggregateKind::Array(ty) => {
270 ty.visit_with(visitor)?;
272 AggregateKind::Tuple => {}
273 AggregateKind::Adt(_, _, substs, user_ty, _) => {
274 substs.visit_with(visitor)?;
275 user_ty.visit_with(visitor)?;
277 AggregateKind::Closure(_, substs) => {
278 substs.visit_with(visitor)?;
280 AggregateKind::Generator(_, substs, _) => {
281 substs.visit_with(visitor)?;
284 fields.visit_with(visitor)
286 ShallowInitBox(ref op, ty) => {
287 op.visit_with(visitor)?;
288 ty.visit_with(visitor)
294 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
295 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
298 ) -> Result<Self, F::Error> {
300 Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?),
301 Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?),
302 Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
306 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
308 Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
309 Operand::Constant(ref c) => c.visit_with(visitor),
314 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
315 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
318 ) -> Result<Self, F::Error> {
319 use crate::mir::ProjectionElem::*;
323 Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
324 Index(v) => Index(v.try_fold_with(folder)?),
325 Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
326 ConstantIndex { offset, min_length, from_end } => {
327 ConstantIndex { offset, min_length, from_end }
329 Subslice { from, to, from_end } => Subslice { from, to, from_end },
333 fn super_visit_with<Vs: TypeVisitor<'tcx>>(
336 ) -> ControlFlow<Vs::BreakTy> {
337 use crate::mir::ProjectionElem::*;
340 Field(_, ty) => ty.visit_with(visitor),
341 Index(v) => v.visit_with(visitor),
342 _ => ControlFlow::CONTINUE,
347 impl<'tcx> TypeFoldable<'tcx> for Field {
348 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
351 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
352 ControlFlow::CONTINUE
356 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
357 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
360 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
361 ControlFlow::CONTINUE
365 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
366 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
369 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
370 ControlFlow::CONTINUE
374 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
375 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
378 ) -> Result<Self, F::Error> {
381 user_ty: self.user_ty.try_fold_with(folder)?,
382 literal: self.literal.try_fold_with(folder)?,
385 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
386 self.literal.visit_with(visitor)?;
387 self.user_ty.visit_with(visitor)
391 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
393 fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
394 folder.try_fold_mir_const(self)
397 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
400 ) -> Result<Self, F::Error> {
402 ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
403 ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
407 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
409 ConstantKind::Ty(c) => c.visit_with(visitor),
410 ConstantKind::Val(_, t) => t.visit_with(visitor),