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