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) -> Self {
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.map(|(loc, dest)| (loc.fold_with(folder), dest));
48 func: func.fold_with(folder),
49 args: args.fold_with(folder),
56 Assert { cond, expected, msg, target, cleanup } => {
59 BoundsCheck { len, index } => {
60 BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
62 Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)),
63 OverflowNeg(op) => OverflowNeg(op.fold_with(folder)),
64 DivisionByZero(op) => DivisionByZero(op.fold_with(folder)),
65 RemainderByZero(op) => RemainderByZero(op.fold_with(folder)),
66 ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
68 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
70 GeneratorDrop => GeneratorDrop,
74 Unreachable => Unreachable,
75 FalseEdge { real_target, imaginary_target } => {
76 FalseEdge { real_target, imaginary_target }
78 FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
79 InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
81 operands: operands.fold_with(folder),
87 Terminator { source_info: self.source_info, kind }
90 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
91 use crate::mir::TerminatorKind::*;
94 SwitchInt { ref discr, switch_ty, .. } => {
95 discr.visit_with(visitor)?;
96 switch_ty.visit_with(visitor)
98 Drop { ref place, .. } => place.visit_with(visitor),
99 DropAndReplace { ref place, ref value, .. } => {
100 place.visit_with(visitor)?;
101 value.visit_with(visitor)
103 Yield { ref value, .. } => value.visit_with(visitor),
104 Call { ref func, ref args, ref destination, .. } => {
105 if let Some((ref loc, _)) = *destination {
106 loc.visit_with(visitor)?;
108 func.visit_with(visitor)?;
109 args.visit_with(visitor)
111 Assert { ref cond, ref msg, .. } => {
112 cond.visit_with(visitor)?;
115 BoundsCheck { ref len, ref index } => {
116 len.visit_with(visitor)?;
117 index.visit_with(visitor)
119 Overflow(_, l, r) => {
120 l.visit_with(visitor)?;
121 r.visit_with(visitor)
123 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
124 op.visit_with(visitor)
126 ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
129 InlineAsm { ref operands, .. } => operands.visit_with(visitor),
137 | FalseUnwind { .. } => ControlFlow::CONTINUE,
142 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
143 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
147 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
148 ControlFlow::CONTINUE
152 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
153 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
154 Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
157 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
158 self.local.visit_with(visitor)?;
159 self.projection.visit_with(visitor)
163 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
164 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
165 ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
168 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
169 self.iter().try_for_each(|t| t.visit_with(visitor))
173 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
174 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
175 use crate::mir::Rvalue::*;
177 Use(op) => Use(op.fold_with(folder)),
178 Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
179 ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
180 Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)),
181 AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)),
182 Len(place) => Len(place.fold_with(folder)),
183 Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
184 BinaryOp(op, box (rhs, lhs)) => {
185 BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
187 CheckedBinaryOp(op, box (rhs, lhs)) => {
188 CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
190 UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)),
191 Discriminant(place) => Discriminant(place.fold_with(folder)),
192 NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
193 Aggregate(kind, fields) => {
194 let kind = kind.map_id(|kind| match kind {
195 AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
196 AggregateKind::Tuple => AggregateKind::Tuple,
197 AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
200 substs.fold_with(folder),
201 user_ty.fold_with(folder),
204 AggregateKind::Closure(id, substs) => {
205 AggregateKind::Closure(id, substs.fold_with(folder))
207 AggregateKind::Generator(id, substs, movablity) => {
208 AggregateKind::Generator(id, substs.fold_with(folder), movablity)
211 Aggregate(kind, fields.fold_with(folder))
213 ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
217 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
218 use crate::mir::Rvalue::*;
220 Use(ref op) => op.visit_with(visitor),
221 Repeat(ref op, _) => op.visit_with(visitor),
222 ThreadLocalRef(did) => did.visit_with(visitor),
223 Ref(region, _, ref place) => {
224 region.visit_with(visitor)?;
225 place.visit_with(visitor)
227 AddressOf(_, ref place) => place.visit_with(visitor),
228 Len(ref place) => place.visit_with(visitor),
229 Cast(_, ref op, ty) => {
230 op.visit_with(visitor)?;
231 ty.visit_with(visitor)
233 BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
234 rhs.visit_with(visitor)?;
235 lhs.visit_with(visitor)
237 UnaryOp(_, ref val) => val.visit_with(visitor),
238 Discriminant(ref place) => place.visit_with(visitor),
239 NullaryOp(_, ty) => ty.visit_with(visitor),
240 Aggregate(ref kind, ref fields) => {
242 AggregateKind::Array(ty) => {
243 ty.visit_with(visitor)?;
245 AggregateKind::Tuple => {}
246 AggregateKind::Adt(_, _, substs, user_ty, _) => {
247 substs.visit_with(visitor)?;
248 user_ty.visit_with(visitor)?;
250 AggregateKind::Closure(_, substs) => {
251 substs.visit_with(visitor)?;
253 AggregateKind::Generator(_, substs, _) => {
254 substs.visit_with(visitor)?;
257 fields.visit_with(visitor)
259 ShallowInitBox(ref op, ty) => {
260 op.visit_with(visitor)?;
261 ty.visit_with(visitor)
267 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
268 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
270 Operand::Copy(place) => Operand::Copy(place.fold_with(folder)),
271 Operand::Move(place) => Operand::Move(place.fold_with(folder)),
272 Operand::Constant(c) => Operand::Constant(c.fold_with(folder)),
276 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
278 Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
279 Operand::Constant(ref c) => c.visit_with(visitor),
284 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
285 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
286 use crate::mir::ProjectionElem::*;
290 Field(f, ty) => Field(f, ty.fold_with(folder)),
291 Index(v) => Index(v.fold_with(folder)),
292 Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
293 ConstantIndex { offset, min_length, from_end } => {
294 ConstantIndex { offset, min_length, from_end }
296 Subslice { from, to, from_end } => Subslice { from, to, from_end },
300 fn super_visit_with<Vs: TypeVisitor<'tcx>>(
303 ) -> ControlFlow<Vs::BreakTy> {
304 use crate::mir::ProjectionElem::*;
307 Field(_, ty) => ty.visit_with(visitor),
308 Index(v) => v.visit_with(visitor),
309 _ => ControlFlow::CONTINUE,
314 impl<'tcx> TypeFoldable<'tcx> for Field {
315 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
318 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
319 ControlFlow::CONTINUE
323 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
324 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
327 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
328 ControlFlow::CONTINUE
332 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
333 fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
336 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
337 ControlFlow::CONTINUE
341 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
342 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
345 user_ty: self.user_ty.fold_with(folder),
346 literal: self.literal.fold_with(folder),
349 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
350 self.literal.visit_with(visitor)?;
351 self.user_ty.visit_with(visitor)
355 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
357 fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
358 folder.fold_mir_const(self)
361 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
363 ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
364 ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)),
368 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
370 ConstantKind::Ty(c) => c.visit_with(visitor),
371 ConstantKind::Val(_, t) => t.visit_with(visitor),