]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
Rollup merge of #90832 - cuviper:relnotes-1.57.0, r=Mark-Simulacrum
[rust.git] / compiler / rustc_middle / src / mir / type_foldable.rs
1 //! `TypeFoldable` implementations for MIR types
2
3 use super::*;
4 use crate::ty;
5 use rustc_data_structures::functor::IdFunctor;
6
7 TrivialTypeFoldableAndLiftImpls! {
8     BlockTailInfo,
9     MirPhase,
10     SourceInfo,
11     FakeReadCause,
12     RetagKind,
13     SourceScope,
14     SourceScopeLocalData,
15     UserTypeAnnotationIndex,
16 }
17
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::*;
21
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)?,
27                 targets,
28             },
29             Drop { place, target, unwind } => {
30                 Drop { place: place.fold_with(folder)?, target, unwind }
31             }
32             DropAndReplace { place, value, target, unwind } => DropAndReplace {
33                 place: place.fold_with(folder)?,
34                 value: value.fold_with(folder)?,
35                 target,
36                 unwind,
37             },
38             Yield { value, resume, resume_arg, drop } => Yield {
39                 value: value.fold_with(folder)?,
40                 resume,
41                 resume_arg: resume_arg.fold_with(folder)?,
42                 drop,
43             },
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))))
47                     .transpose()?;
48
49                 Call {
50                     func: func.fold_with(folder)?,
51                     args: args.fold_with(folder)?,
52                     destination: dest,
53                     cleanup,
54                     from_hir_call,
55                     fn_span,
56                 }
57             }
58             Assert { cond, expected, msg, target, cleanup } => {
59                 use AssertKind::*;
60                 let msg = match msg {
61                     BoundsCheck { len, index } => {
62                         BoundsCheck { len: len.fold_with(folder)?, index: index.fold_with(folder)? }
63                     }
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,
69                 };
70                 Assert { cond: cond.fold_with(folder)?, expected, msg, target, cleanup }
71             }
72             GeneratorDrop => GeneratorDrop,
73             Resume => Resume,
74             Abort => Abort,
75             Return => Return,
76             Unreachable => Unreachable,
77             FalseEdge { real_target, imaginary_target } => {
78                 FalseEdge { real_target, imaginary_target }
79             }
80             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
81             InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
82                 template,
83                 operands: operands.fold_with(folder)?,
84                 options,
85                 line_spans,
86                 destination,
87             },
88         };
89         Ok(Terminator { source_info: self.source_info, kind })
90     }
91
92     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
93         use crate::mir::TerminatorKind::*;
94
95         match self.kind {
96             SwitchInt { ref discr, switch_ty, .. } => {
97                 discr.visit_with(visitor)?;
98                 switch_ty.visit_with(visitor)
99             }
100             Drop { ref place, .. } => place.visit_with(visitor),
101             DropAndReplace { ref place, ref value, .. } => {
102                 place.visit_with(visitor)?;
103                 value.visit_with(visitor)
104             }
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)?;
109                 };
110                 func.visit_with(visitor)?;
111                 args.visit_with(visitor)
112             }
113             Assert { ref cond, ref msg, .. } => {
114                 cond.visit_with(visitor)?;
115                 use AssertKind::*;
116                 match msg {
117                     BoundsCheck { ref len, ref index } => {
118                         len.visit_with(visitor)?;
119                         index.visit_with(visitor)
120                     }
121                     Overflow(_, l, r) => {
122                         l.visit_with(visitor)?;
123                         r.visit_with(visitor)
124                     }
125                     OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
126                         op.visit_with(visitor)
127                     }
128                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
129                 }
130             }
131             InlineAsm { ref operands, .. } => operands.visit_with(visitor),
132             Goto { .. }
133             | Resume
134             | Abort
135             | Return
136             | GeneratorDrop
137             | Unreachable
138             | FalseEdge { .. }
139             | FalseUnwind { .. } => ControlFlow::CONTINUE,
140         }
141     }
142 }
143
144 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
145     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
146         Ok(self)
147     }
148
149     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
150         ControlFlow::CONTINUE
151     }
152 }
153
154 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
155     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
156         Ok(Place {
157             local: self.local.fold_with(folder)?,
158             projection: self.projection.fold_with(folder)?,
159         })
160     }
161
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)
165     }
166 }
167
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))
171     }
172
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))
175     }
176 }
177
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::*;
181         Ok(match self {
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)?)))
191             }
192             CheckedBinaryOp(op, box (rhs, lhs)) => {
193                 CheckedBinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?)))
194             }
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| {
200                     Ok(match 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(
204                             def,
205                             v,
206                             substs.fold_with(folder)?,
207                             user_ty.fold_with(folder)?,
208                             n,
209                         ),
210                         AggregateKind::Closure(id, substs) => {
211                             AggregateKind::Closure(id, substs.fold_with(folder)?)
212                         }
213                         AggregateKind::Generator(id, substs, movablity) => {
214                             AggregateKind::Generator(id, substs.fold_with(folder)?, movablity)
215                         }
216                     })
217                 })?;
218                 Aggregate(kind, fields.fold_with(folder)?)
219             }
220             ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder)?, ty.fold_with(folder)?),
221         })
222     }
223
224     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
225         use crate::mir::Rvalue::*;
226         match *self {
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)
233             }
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)
239             }
240             BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
241                 rhs.visit_with(visitor)?;
242                 lhs.visit_with(visitor)
243             }
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) => {
248                 match **kind {
249                     AggregateKind::Array(ty) => {
250                         ty.visit_with(visitor)?;
251                     }
252                     AggregateKind::Tuple => {}
253                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
254                         substs.visit_with(visitor)?;
255                         user_ty.visit_with(visitor)?;
256                     }
257                     AggregateKind::Closure(_, substs) => {
258                         substs.visit_with(visitor)?;
259                     }
260                     AggregateKind::Generator(_, substs, _) => {
261                         substs.visit_with(visitor)?;
262                     }
263                 }
264                 fields.visit_with(visitor)
265             }
266             ShallowInitBox(ref op, ty) => {
267                 op.visit_with(visitor)?;
268                 ty.visit_with(visitor)
269             }
270         }
271     }
272 }
273
274 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
275     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
276         Ok(match self {
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)?),
280         })
281     }
282
283     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
284         match *self {
285             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
286             Operand::Constant(ref c) => c.visit_with(visitor),
287         }
288     }
289 }
290
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::*;
294
295         Ok(match self {
296             Deref => Deref,
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 }
302             }
303             Subslice { from, to, from_end } => Subslice { from, to, from_end },
304         })
305     }
306
307     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
308         &self,
309         visitor: &mut Vs,
310     ) -> ControlFlow<Vs::BreakTy> {
311         use crate::mir::ProjectionElem::*;
312
313         match self {
314             Field(_, ty) => ty.visit_with(visitor),
315             Index(v) => v.visit_with(visitor),
316             _ => ControlFlow::CONTINUE,
317         }
318     }
319 }
320
321 impl<'tcx> TypeFoldable<'tcx> for Field {
322     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
323         Ok(self)
324     }
325     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
326         ControlFlow::CONTINUE
327     }
328 }
329
330 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
331     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
332         Ok(self)
333     }
334     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
335         ControlFlow::CONTINUE
336     }
337 }
338
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> {
341         Ok(self)
342     }
343     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
344         ControlFlow::CONTINUE
345     }
346 }
347
348 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
349     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
350         Ok(Constant {
351             span: self.span,
352             user_ty: self.user_ty.fold_with(folder)?,
353             literal: self.literal.fold_with(folder)?,
354         })
355     }
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)
359     }
360 }
361
362 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
363     #[inline(always)]
364     fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
365         folder.fold_mir_const(self)
366     }
367
368     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
369         match self {
370             ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)),
371             ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.fold_with(folder)?)),
372         }
373     }
374
375     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
376         match *self {
377             ConstantKind::Ty(c) => c.visit_with(visitor),
378             ConstantKind::Val(_, t) => t.visit_with(visitor),
379         }
380     }
381 }