]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
Rollup merge of #88906 - Kixunil:box-maybe-uninit-write, r=dtolnay
[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 try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
20         self,
21         folder: &mut F,
22     ) -> Result<Self, F::Error> {
23         use crate::mir::TerminatorKind::*;
24
25         let kind = match self.kind {
26             Goto { target } => Goto { target },
27             SwitchInt { discr, switch_ty, targets } => SwitchInt {
28                 discr: discr.try_fold_with(folder)?,
29                 switch_ty: switch_ty.try_fold_with(folder)?,
30                 targets,
31             },
32             Drop { place, target, unwind } => {
33                 Drop { place: place.try_fold_with(folder)?, target, unwind }
34             }
35             DropAndReplace { place, value, target, unwind } => DropAndReplace {
36                 place: place.try_fold_with(folder)?,
37                 value: value.try_fold_with(folder)?,
38                 target,
39                 unwind,
40             },
41             Yield { value, resume, resume_arg, drop } => Yield {
42                 value: value.try_fold_with(folder)?,
43                 resume,
44                 resume_arg: resume_arg.try_fold_with(folder)?,
45                 drop,
46             },
47             Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
48                 let dest = destination
49                     .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest))))
50                     .transpose()?;
51
52                 Call {
53                     func: func.try_fold_with(folder)?,
54                     args: args.try_fold_with(folder)?,
55                     destination: dest,
56                     cleanup,
57                     from_hir_call,
58                     fn_span,
59                 }
60             }
61             Assert { cond, expected, msg, target, cleanup } => {
62                 use AssertKind::*;
63                 let msg = match msg {
64                     BoundsCheck { len, index } => BoundsCheck {
65                         len: len.try_fold_with(folder)?,
66                         index: index.try_fold_with(folder)?,
67                     },
68                     Overflow(op, l, r) => {
69                         Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?)
70                     }
71                     OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?),
72                     DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?),
73                     RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?),
74                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
75                 };
76                 Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup }
77             }
78             GeneratorDrop => GeneratorDrop,
79             Resume => Resume,
80             Abort => Abort,
81             Return => Return,
82             Unreachable => Unreachable,
83             FalseEdge { real_target, imaginary_target } => {
84                 FalseEdge { real_target, imaginary_target }
85             }
86             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
87             InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
88                 template,
89                 operands: operands.try_fold_with(folder)?,
90                 options,
91                 line_spans,
92                 destination,
93             },
94         };
95         Ok(Terminator { source_info: self.source_info, kind })
96     }
97
98     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
99         use crate::mir::TerminatorKind::*;
100
101         match self.kind {
102             SwitchInt { ref discr, switch_ty, .. } => {
103                 discr.visit_with(visitor)?;
104                 switch_ty.visit_with(visitor)
105             }
106             Drop { ref place, .. } => place.visit_with(visitor),
107             DropAndReplace { ref place, ref value, .. } => {
108                 place.visit_with(visitor)?;
109                 value.visit_with(visitor)
110             }
111             Yield { ref value, .. } => value.visit_with(visitor),
112             Call { ref func, ref args, ref destination, .. } => {
113                 if let Some((ref loc, _)) = *destination {
114                     loc.visit_with(visitor)?;
115                 };
116                 func.visit_with(visitor)?;
117                 args.visit_with(visitor)
118             }
119             Assert { ref cond, ref msg, .. } => {
120                 cond.visit_with(visitor)?;
121                 use AssertKind::*;
122                 match msg {
123                     BoundsCheck { ref len, ref index } => {
124                         len.visit_with(visitor)?;
125                         index.visit_with(visitor)
126                     }
127                     Overflow(_, l, r) => {
128                         l.visit_with(visitor)?;
129                         r.visit_with(visitor)
130                     }
131                     OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
132                         op.visit_with(visitor)
133                     }
134                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
135                 }
136             }
137             InlineAsm { ref operands, .. } => operands.visit_with(visitor),
138             Goto { .. }
139             | Resume
140             | Abort
141             | Return
142             | GeneratorDrop
143             | Unreachable
144             | FalseEdge { .. }
145             | FalseUnwind { .. } => ControlFlow::CONTINUE,
146         }
147     }
148 }
149
150 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
151     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
152         Ok(self)
153     }
154
155     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
156         ControlFlow::CONTINUE
157     }
158 }
159
160 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
161     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
162         self,
163         folder: &mut F,
164     ) -> Result<Self, F::Error> {
165         Ok(Place {
166             local: self.local.try_fold_with(folder)?,
167             projection: self.projection.try_fold_with(folder)?,
168         })
169     }
170
171     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
172         self.local.visit_with(visitor)?;
173         self.projection.visit_with(visitor)
174     }
175 }
176
177 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
178     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
179         self,
180         folder: &mut F,
181     ) -> Result<Self, F::Error> {
182         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
183     }
184
185     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
186         self.iter().try_for_each(|t| t.visit_with(visitor))
187     }
188 }
189
190 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
191     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
192         self,
193         folder: &mut F,
194     ) -> Result<Self, F::Error> {
195         use crate::mir::Rvalue::*;
196         Ok(match self {
197             Use(op) => Use(op.try_fold_with(folder)?),
198             Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?),
199             ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?),
200             Ref(region, bk, place) => {
201                 Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?)
202             }
203             AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?),
204             Len(place) => Len(place.try_fold_with(folder)?),
205             Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?),
206             BinaryOp(op, box (rhs, lhs)) => {
207                 BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)))
208             }
209             CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp(
210                 op,
211                 Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)),
212             ),
213             UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?),
214             Discriminant(place) => Discriminant(place.try_fold_with(folder)?),
215             NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?),
216             Aggregate(kind, fields) => {
217                 let kind = kind.try_map_id(|kind| {
218                     Ok(match kind {
219                         AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?),
220                         AggregateKind::Tuple => AggregateKind::Tuple,
221                         AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
222                             def,
223                             v,
224                             substs.try_fold_with(folder)?,
225                             user_ty.try_fold_with(folder)?,
226                             n,
227                         ),
228                         AggregateKind::Closure(id, substs) => {
229                             AggregateKind::Closure(id, substs.try_fold_with(folder)?)
230                         }
231                         AggregateKind::Generator(id, substs, movablity) => {
232                             AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
233                         }
234                     })
235                 })?;
236                 Aggregate(kind, fields.try_fold_with(folder)?)
237             }
238             ShallowInitBox(op, ty) => {
239                 ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
240             }
241         })
242     }
243
244     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
245         use crate::mir::Rvalue::*;
246         match *self {
247             Use(ref op) => op.visit_with(visitor),
248             Repeat(ref op, _) => op.visit_with(visitor),
249             ThreadLocalRef(did) => did.visit_with(visitor),
250             Ref(region, _, ref place) => {
251                 region.visit_with(visitor)?;
252                 place.visit_with(visitor)
253             }
254             AddressOf(_, ref place) => place.visit_with(visitor),
255             Len(ref place) => place.visit_with(visitor),
256             Cast(_, ref op, ty) => {
257                 op.visit_with(visitor)?;
258                 ty.visit_with(visitor)
259             }
260             BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
261                 rhs.visit_with(visitor)?;
262                 lhs.visit_with(visitor)
263             }
264             UnaryOp(_, ref val) => val.visit_with(visitor),
265             Discriminant(ref place) => place.visit_with(visitor),
266             NullaryOp(_, ty) => ty.visit_with(visitor),
267             Aggregate(ref kind, ref fields) => {
268                 match **kind {
269                     AggregateKind::Array(ty) => {
270                         ty.visit_with(visitor)?;
271                     }
272                     AggregateKind::Tuple => {}
273                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
274                         substs.visit_with(visitor)?;
275                         user_ty.visit_with(visitor)?;
276                     }
277                     AggregateKind::Closure(_, substs) => {
278                         substs.visit_with(visitor)?;
279                     }
280                     AggregateKind::Generator(_, substs, _) => {
281                         substs.visit_with(visitor)?;
282                     }
283                 }
284                 fields.visit_with(visitor)
285             }
286             ShallowInitBox(ref op, ty) => {
287                 op.visit_with(visitor)?;
288                 ty.visit_with(visitor)
289             }
290         }
291     }
292 }
293
294 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
295     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
296         self,
297         folder: &mut F,
298     ) -> Result<Self, F::Error> {
299         Ok(match self {
300             Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?),
301             Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?),
302             Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
303         })
304     }
305
306     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
307         match *self {
308             Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
309             Operand::Constant(ref c) => c.visit_with(visitor),
310         }
311     }
312 }
313
314 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
315     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
316         self,
317         folder: &mut F,
318     ) -> Result<Self, F::Error> {
319         use crate::mir::ProjectionElem::*;
320
321         Ok(match self {
322             Deref => Deref,
323             Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
324             Index(v) => Index(v.try_fold_with(folder)?),
325             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
326             ConstantIndex { offset, min_length, from_end } => {
327                 ConstantIndex { offset, min_length, from_end }
328             }
329             Subslice { from, to, from_end } => Subslice { from, to, from_end },
330         })
331     }
332
333     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
334         &self,
335         visitor: &mut Vs,
336     ) -> ControlFlow<Vs::BreakTy> {
337         use crate::mir::ProjectionElem::*;
338
339         match self {
340             Field(_, ty) => ty.visit_with(visitor),
341             Index(v) => v.visit_with(visitor),
342             _ => ControlFlow::CONTINUE,
343         }
344     }
345 }
346
347 impl<'tcx> TypeFoldable<'tcx> for Field {
348     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
349         Ok(self)
350     }
351     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
352         ControlFlow::CONTINUE
353     }
354 }
355
356 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
357     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
358         Ok(self)
359     }
360     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
361         ControlFlow::CONTINUE
362     }
363 }
364
365 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
366     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
367         Ok(self)
368     }
369     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
370         ControlFlow::CONTINUE
371     }
372 }
373
374 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
375     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
376         self,
377         folder: &mut F,
378     ) -> Result<Self, F::Error> {
379         Ok(Constant {
380             span: self.span,
381             user_ty: self.user_ty.try_fold_with(folder)?,
382             literal: self.literal.try_fold_with(folder)?,
383         })
384     }
385     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
386         self.literal.visit_with(visitor)?;
387         self.user_ty.visit_with(visitor)
388     }
389 }
390
391 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
392     #[inline(always)]
393     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
394         folder.try_fold_mir_const(self)
395     }
396
397     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
398         self,
399         folder: &mut F,
400     ) -> Result<Self, F::Error> {
401         match self {
402             ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
403             ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
404         }
405     }
406
407     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
408         match *self {
409             ConstantKind::Ty(c) => c.visit_with(visitor),
410             ConstantKind::Val(_, t) => t.visit_with(visitor),
411         }
412     }
413 }