]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
391bd8be7e4c59502f80a7236d37e30658d32ad4
[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     SourceScopeLocalData,
14     UserTypeAnnotationIndex,
15 }
16
17 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
18     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
19         use crate::mir::TerminatorKind::*;
20
21         let kind = match self.kind {
22             Goto { target } => Goto { target },
23             SwitchInt { ref discr, switch_ty, ref targets } => SwitchInt {
24                 discr: discr.fold_with(folder),
25                 switch_ty: switch_ty.fold_with(folder),
26                 targets: targets.clone(),
27             },
28             Drop { ref place, target, unwind } => {
29                 Drop { place: place.fold_with(folder), target, unwind }
30             }
31             DropAndReplace { ref place, ref value, target, unwind } => DropAndReplace {
32                 place: place.fold_with(folder),
33                 value: value.fold_with(folder),
34                 target,
35                 unwind,
36             },
37             Yield { ref value, resume, ref resume_arg, drop } => Yield {
38                 value: value.fold_with(folder),
39                 resume,
40                 resume_arg: resume_arg.fold_with(folder),
41                 drop,
42             },
43             Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
44                 let dest =
45                     destination.as_ref().map(|&(ref 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 { ref cond, expected, ref 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.clone(),
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, ref 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<()> {
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                 if cond.visit_with(visitor).is_break() {
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                 } else {
129                     ControlFlow::CONTINUE
130                 }
131             }
132             InlineAsm { ref operands, .. } => operands.visit_with(visitor),
133             Goto { .. }
134             | Resume
135             | Abort
136             | Return
137             | GeneratorDrop
138             | Unreachable
139             | FalseEdge { .. }
140             | FalseUnwind { .. } => ControlFlow::CONTINUE,
141         }
142     }
143 }
144
145 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
146     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
147         *self
148     }
149
150     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
151         ControlFlow::CONTINUE
152     }
153 }
154
155 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
156     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
157         Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
158     }
159
160     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
161         self.local.visit_with(visitor)?;
162         self.projection.visit_with(visitor)
163     }
164 }
165
166 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
167     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
168         let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
169         folder.tcx().intern_place_elems(&v)
170     }
171
172     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
173         self.iter().try_for_each(|t| t.visit_with(visitor))
174     }
175 }
176
177 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
178     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
179         use crate::mir::Rvalue::*;
180         match *self {
181             Use(ref op) => Use(op.fold_with(folder)),
182             Repeat(ref op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
183             ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
184             Ref(region, bk, ref place) => {
185                 Ref(region.fold_with(folder), bk, place.fold_with(folder))
186             }
187             AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)),
188             Len(ref place) => Len(place.fold_with(folder)),
189             Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
190             BinaryOp(op, ref rhs, ref lhs) => {
191                 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
192             }
193             CheckedBinaryOp(op, ref rhs, ref lhs) => {
194                 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
195             }
196             UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
197             Discriminant(ref place) => Discriminant(place.fold_with(folder)),
198             NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
199             Aggregate(ref kind, ref fields) => {
200                 let kind = box 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                 Aggregate(kind, fields.fold_with(folder))
218             }
219         }
220     }
221
222     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
223         use crate::mir::Rvalue::*;
224         match *self {
225             Use(ref op) => op.visit_with(visitor),
226             Repeat(ref op, _) => op.visit_with(visitor),
227             ThreadLocalRef(did) => did.visit_with(visitor),
228             Ref(region, _, ref place) => {
229                 region.visit_with(visitor)?;
230                 place.visit_with(visitor)
231             }
232             AddressOf(_, ref place) => place.visit_with(visitor),
233             Len(ref place) => place.visit_with(visitor),
234             Cast(_, ref op, ty) => {
235                 op.visit_with(visitor)?;
236                 ty.visit_with(visitor)
237             }
238             BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
239                 rhs.visit_with(visitor)?;
240                 lhs.visit_with(visitor)
241             }
242             UnaryOp(_, ref val) => val.visit_with(visitor),
243             Discriminant(ref place) => place.visit_with(visitor),
244             NullaryOp(_, ty) => ty.visit_with(visitor),
245             Aggregate(ref kind, ref fields) => {
246                 match **kind {
247                     AggregateKind::Array(ty) => {
248                         ty.visit_with(visitor)?;
249                     }
250                     AggregateKind::Tuple => {}
251                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
252                         substs.visit_with(visitor)?;
253                         user_ty.visit_with(visitor)?;
254                     }
255                     AggregateKind::Closure(_, substs) => {
256                         substs.visit_with(visitor)?;
257                     }
258                     AggregateKind::Generator(_, substs, _) => {
259                         substs.visit_with(visitor)?;
260                     }
261                 }
262                 fields.visit_with(visitor)
263             }
264         }
265     }
266 }
267
268 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
269     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
270         match *self {
271             Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
272             Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
273             Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
274         }
275     }
276
277     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
278         match *self {
279             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
280             Operand::Constant(ref c) => c.visit_with(visitor),
281         }
282     }
283 }
284
285 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
286     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
287         use crate::mir::ProjectionElem::*;
288
289         match *self {
290             Deref => Deref,
291             Field(f, ty) => Field(f, ty.fold_with(folder)),
292             Index(v) => Index(v.fold_with(folder)),
293             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
294             ConstantIndex { offset, min_length, from_end } => {
295                 ConstantIndex { offset, min_length, from_end }
296             }
297             Subslice { from, to, from_end } => Subslice { from, to, from_end },
298         }
299     }
300
301     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<()> {
302         use crate::mir::ProjectionElem::*;
303
304         match self {
305             Field(_, ty) => ty.visit_with(visitor),
306             Index(v) => v.visit_with(visitor),
307             _ => ControlFlow::CONTINUE,
308         }
309     }
310 }
311
312 impl<'tcx> TypeFoldable<'tcx> for Field {
313     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
314         *self
315     }
316     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
317         ControlFlow::CONTINUE
318     }
319 }
320
321 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
322     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
323         *self
324     }
325     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
326         ControlFlow::CONTINUE
327     }
328 }
329
330 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
331     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
332         self.clone()
333     }
334     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
335         ControlFlow::CONTINUE
336     }
337 }
338
339 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
340     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
341         Constant {
342             span: self.span,
343             user_ty: self.user_ty.fold_with(folder),
344             literal: self.literal.fold_with(folder),
345         }
346     }
347     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
348         self.literal.visit_with(visitor)
349     }
350 }