]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
Rollup merge of #88452 - xu-cheng:vecdeque-from-array, r=m-ou-se
[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) -> Self {
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.map(|(loc, dest)| (loc.fold_with(folder), dest));
46
47                 Call {
48                     func: func.fold_with(folder),
49                     args: args.fold_with(folder),
50                     destination: dest,
51                     cleanup,
52                     from_hir_call,
53                     fn_span,
54                 }
55             }
56             Assert { cond, expected, msg, target, cleanup } => {
57                 use AssertKind::*;
58                 let msg = match msg {
59                     BoundsCheck { len, index } => {
60                         BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
61                     }
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,
67                 };
68                 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
69             }
70             GeneratorDrop => GeneratorDrop,
71             Resume => Resume,
72             Abort => Abort,
73             Return => Return,
74             Unreachable => Unreachable,
75             FalseEdge { real_target, imaginary_target } => {
76                 FalseEdge { real_target, imaginary_target }
77             }
78             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
79             InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
80                 template,
81                 operands: operands.fold_with(folder),
82                 options,
83                 line_spans,
84                 destination,
85             },
86         };
87         Terminator { source_info: self.source_info, kind }
88     }
89
90     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
91         use crate::mir::TerminatorKind::*;
92
93         match self.kind {
94             SwitchInt { ref discr, switch_ty, .. } => {
95                 discr.visit_with(visitor)?;
96                 switch_ty.visit_with(visitor)
97             }
98             Drop { ref place, .. } => place.visit_with(visitor),
99             DropAndReplace { ref place, ref value, .. } => {
100                 place.visit_with(visitor)?;
101                 value.visit_with(visitor)
102             }
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)?;
107                 };
108                 func.visit_with(visitor)?;
109                 args.visit_with(visitor)
110             }
111             Assert { ref cond, ref msg, .. } => {
112                 cond.visit_with(visitor)?;
113                 use AssertKind::*;
114                 match msg {
115                     BoundsCheck { ref len, ref index } => {
116                         len.visit_with(visitor)?;
117                         index.visit_with(visitor)
118                     }
119                     Overflow(_, l, r) => {
120                         l.visit_with(visitor)?;
121                         r.visit_with(visitor)
122                     }
123                     OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
124                         op.visit_with(visitor)
125                     }
126                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
127                 }
128             }
129             InlineAsm { ref operands, .. } => operands.visit_with(visitor),
130             Goto { .. }
131             | Resume
132             | Abort
133             | Return
134             | GeneratorDrop
135             | Unreachable
136             | FalseEdge { .. }
137             | FalseUnwind { .. } => ControlFlow::CONTINUE,
138         }
139     }
140 }
141
142 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
143     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
144         self
145     }
146
147     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
148         ControlFlow::CONTINUE
149     }
150 }
151
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) }
155     }
156
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)
160     }
161 }
162
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))
166     }
167
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))
170     }
171 }
172
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::*;
176         match self {
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))))
186             }
187             CheckedBinaryOp(op, box (rhs, lhs)) => {
188                 CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
189             }
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(
198                         def,
199                         v,
200                         substs.fold_with(folder),
201                         user_ty.fold_with(folder),
202                         n,
203                     ),
204                     AggregateKind::Closure(id, substs) => {
205                         AggregateKind::Closure(id, substs.fold_with(folder))
206                     }
207                     AggregateKind::Generator(id, substs, movablity) => {
208                         AggregateKind::Generator(id, substs.fold_with(folder), movablity)
209                     }
210                 });
211                 Aggregate(kind, fields.fold_with(folder))
212             }
213             ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
214         }
215     }
216
217     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
218         use crate::mir::Rvalue::*;
219         match *self {
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)
226             }
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)
232             }
233             BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
234                 rhs.visit_with(visitor)?;
235                 lhs.visit_with(visitor)
236             }
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) => {
241                 match **kind {
242                     AggregateKind::Array(ty) => {
243                         ty.visit_with(visitor)?;
244                     }
245                     AggregateKind::Tuple => {}
246                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
247                         substs.visit_with(visitor)?;
248                         user_ty.visit_with(visitor)?;
249                     }
250                     AggregateKind::Closure(_, substs) => {
251                         substs.visit_with(visitor)?;
252                     }
253                     AggregateKind::Generator(_, substs, _) => {
254                         substs.visit_with(visitor)?;
255                     }
256                 }
257                 fields.visit_with(visitor)
258             }
259             ShallowInitBox(ref op, ty) => {
260                 op.visit_with(visitor)?;
261                 ty.visit_with(visitor)
262             }
263         }
264     }
265 }
266
267 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
268     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
269         match 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)),
273         }
274     }
275
276     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
277         match *self {
278             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
279             Operand::Constant(ref c) => c.visit_with(visitor),
280         }
281     }
282 }
283
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::*;
287
288         match self {
289             Deref => Deref,
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 }
295             }
296             Subslice { from, to, from_end } => Subslice { from, to, from_end },
297         }
298     }
299
300     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
301         &self,
302         visitor: &mut Vs,
303     ) -> ControlFlow<Vs::BreakTy> {
304         use crate::mir::ProjectionElem::*;
305
306         match self {
307             Field(_, ty) => ty.visit_with(visitor),
308             Index(v) => v.visit_with(visitor),
309             _ => ControlFlow::CONTINUE,
310         }
311     }
312 }
313
314 impl<'tcx> TypeFoldable<'tcx> for Field {
315     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
316         self
317     }
318     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
319         ControlFlow::CONTINUE
320     }
321 }
322
323 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
324     fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
325         self
326     }
327     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
328         ControlFlow::CONTINUE
329     }
330 }
331
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 {
334         self
335     }
336     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
337         ControlFlow::CONTINUE
338     }
339 }
340
341 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
342     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
343         Constant {
344             span: self.span,
345             user_ty: self.user_ty.fold_with(folder),
346             literal: self.literal.fold_with(folder),
347         }
348     }
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)
352     }
353 }
354
355 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
356     #[inline(always)]
357     fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
358         folder.fold_mir_const(self)
359     }
360
361     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
362         match self {
363             ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
364             ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)),
365         }
366     }
367
368     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
369         match *self {
370             ConstantKind::Ty(c) => c.visit_with(visitor),
371             ConstantKind::Val(_, t) => t.visit_with(visitor),
372         }
373     }
374 }