]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
Rollup merge of #76299 - CDirkx:ip-tests, r=matklad
[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
6 CloneTypeFoldableAndLiftImpls! {
7     BlockTailInfo,
8     MirPhase,
9     SourceInfo,
10     FakeReadCause,
11     RetagKind,
12     SourceScope,
13     SourceScopeData,
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 { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
25                 discr: discr.fold_with(folder),
26                 switch_ty: switch_ty.fold_with(folder),
27                 values: values.clone(),
28                 targets: targets.clone(),
29             },
30             Drop { ref place, target, unwind } => {
31                 Drop { place: place.fold_with(folder), target, unwind }
32             }
33             DropAndReplace { ref place, ref value, target, unwind } => DropAndReplace {
34                 place: place.fold_with(folder),
35                 value: value.fold_with(folder),
36                 target,
37                 unwind,
38             },
39             Yield { ref value, resume, ref resume_arg, drop } => Yield {
40                 value: value.fold_with(folder),
41                 resume,
42                 resume_arg: resume_arg.fold_with(folder),
43                 drop,
44             },
45             Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
46                 let dest =
47                     destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
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 { ref cond, expected, ref 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.clone(),
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, ref operands, options, line_spans, destination } => InlineAsm {
82                 template,
83                 operands: operands.fold_with(folder),
84                 options,
85                 line_spans,
86                 destination,
87             },
88         };
89         Terminator { source_info: self.source_info, kind }
90     }
91
92     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
93         use crate::mir::TerminatorKind::*;
94
95         match self.kind {
96             SwitchInt { ref discr, switch_ty, .. } => {
97                 discr.visit_with(visitor) || switch_ty.visit_with(visitor)
98             }
99             Drop { ref place, .. } => place.visit_with(visitor),
100             DropAndReplace { ref place, ref value, .. } => {
101                 place.visit_with(visitor) || value.visit_with(visitor)
102             }
103             Yield { ref value, .. } => value.visit_with(visitor),
104             Call { ref func, ref args, ref destination, .. } => {
105                 let dest = if let Some((ref loc, _)) = *destination {
106                     loc.visit_with(visitor)
107                 } else {
108                     false
109                 };
110                 dest || func.visit_with(visitor) || args.visit_with(visitor)
111             }
112             Assert { ref cond, ref msg, .. } => {
113                 if cond.visit_with(visitor) {
114                     use AssertKind::*;
115                     match msg {
116                         BoundsCheck { ref len, ref index } => {
117                             len.visit_with(visitor) || index.visit_with(visitor)
118                         }
119                         Overflow(_, l, r) => l.visit_with(visitor) || r.visit_with(visitor),
120                         OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
121                             op.visit_with(visitor)
122                         }
123                         ResumedAfterReturn(_) | ResumedAfterPanic(_) => false,
124                     }
125                 } else {
126                     false
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 { .. } => false,
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) -> bool {
148         false
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) -> bool {
158         self.local.visit_with(visitor) || self.projection.visit_with(visitor)
159     }
160 }
161
162 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
163     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
164         let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
165         folder.tcx().intern_place_elems(&v)
166     }
167
168     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
169         self.iter().any(|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(ref op) => Use(op.fold_with(folder)),
178             Repeat(ref op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
179             ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
180             Ref(region, bk, ref place) => {
181                 Ref(region.fold_with(folder), bk, place.fold_with(folder))
182             }
183             AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)),
184             Len(ref place) => Len(place.fold_with(folder)),
185             Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
186             BinaryOp(op, ref rhs, ref lhs) => {
187                 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
188             }
189             CheckedBinaryOp(op, ref rhs, ref lhs) => {
190                 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
191             }
192             UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
193             Discriminant(ref place) => Discriminant(place.fold_with(folder)),
194             NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
195             Aggregate(ref kind, ref fields) => {
196                 let kind = box match **kind {
197                     AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
198                     AggregateKind::Tuple => AggregateKind::Tuple,
199                     AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
200                         def,
201                         v,
202                         substs.fold_with(folder),
203                         user_ty.fold_with(folder),
204                         n,
205                     ),
206                     AggregateKind::Closure(id, substs) => {
207                         AggregateKind::Closure(id, substs.fold_with(folder))
208                     }
209                     AggregateKind::Generator(id, substs, movablity) => {
210                         AggregateKind::Generator(id, substs.fold_with(folder), movablity)
211                     }
212                 };
213                 Aggregate(kind, fields.fold_with(folder))
214             }
215         }
216     }
217
218     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
219         use crate::mir::Rvalue::*;
220         match *self {
221             Use(ref op) => op.visit_with(visitor),
222             Repeat(ref op, _) => op.visit_with(visitor),
223             ThreadLocalRef(did) => did.visit_with(visitor),
224             Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
225             AddressOf(_, ref place) => place.visit_with(visitor),
226             Len(ref place) => place.visit_with(visitor),
227             Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
228             BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
229                 rhs.visit_with(visitor) || lhs.visit_with(visitor)
230             }
231             UnaryOp(_, ref val) => val.visit_with(visitor),
232             Discriminant(ref place) => place.visit_with(visitor),
233             NullaryOp(_, ty) => ty.visit_with(visitor),
234             Aggregate(ref kind, ref fields) => {
235                 (match **kind {
236                     AggregateKind::Array(ty) => ty.visit_with(visitor),
237                     AggregateKind::Tuple => false,
238                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
239                         substs.visit_with(visitor) || user_ty.visit_with(visitor)
240                     }
241                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
242                     AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
243                 }) || fields.visit_with(visitor)
244             }
245         }
246     }
247 }
248
249 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
250     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
251         match *self {
252             Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
253             Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
254             Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
255         }
256     }
257
258     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
259         match *self {
260             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
261             Operand::Constant(ref c) => c.visit_with(visitor),
262         }
263     }
264 }
265
266 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
267     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
268         use crate::mir::ProjectionElem::*;
269
270         match *self {
271             Deref => Deref,
272             Field(f, ty) => Field(f, ty.fold_with(folder)),
273             Index(v) => Index(v.fold_with(folder)),
274             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
275             ConstantIndex { offset, min_length, from_end } => {
276                 ConstantIndex { offset, min_length, from_end }
277             }
278             Subslice { from, to, from_end } => Subslice { from, to, from_end },
279         }
280     }
281
282     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
283         use crate::mir::ProjectionElem::*;
284
285         match self {
286             Field(_, ty) => ty.visit_with(visitor),
287             Index(v) => v.visit_with(visitor),
288             _ => false,
289         }
290     }
291 }
292
293 impl<'tcx> TypeFoldable<'tcx> for Field {
294     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
295         *self
296     }
297     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
298         false
299     }
300 }
301
302 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
303     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
304         *self
305     }
306     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
307         false
308     }
309 }
310
311 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
312     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
313         self.clone()
314     }
315     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
316         false
317     }
318 }
319
320 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
321     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
322         Constant {
323             span: self.span,
324             user_ty: self.user_ty.fold_with(folder),
325             literal: self.literal.fold_with(folder),
326         }
327     }
328     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
329         self.literal.visit_with(visitor)
330     }
331 }