]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/type_foldable.rs
Rollup merge of #99711 - tmiasko:coverage, r=wesleywiser
[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 TrivialTypeTraversalAndLiftImpls! {
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_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
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.try_fold_with(folder)?,
26                 switch_ty: switch_ty.try_fold_with(folder)?,
27                 targets,
28             },
29             Drop { place, target, unwind } => {
30                 Drop { place: place.try_fold_with(folder)?, target, unwind }
31             }
32             DropAndReplace { place, value, target, unwind } => DropAndReplace {
33                 place: place.try_fold_with(folder)?,
34                 value: value.try_fold_with(folder)?,
35                 target,
36                 unwind,
37             },
38             Yield { value, resume, resume_arg, drop } => Yield {
39                 value: value.try_fold_with(folder)?,
40                 resume,
41                 resume_arg: resume_arg.try_fold_with(folder)?,
42                 drop,
43             },
44             Call { func, args, destination, target, cleanup, from_hir_call, fn_span } => Call {
45                 func: func.try_fold_with(folder)?,
46                 args: args.try_fold_with(folder)?,
47                 destination: destination.try_fold_with(folder)?,
48                 target,
49                 cleanup,
50                 from_hir_call,
51                 fn_span,
52             },
53             Assert { cond, expected, msg, target, cleanup } => {
54                 use AssertKind::*;
55                 let msg = match msg {
56                     BoundsCheck { len, index } => BoundsCheck {
57                         len: len.try_fold_with(folder)?,
58                         index: index.try_fold_with(folder)?,
59                     },
60                     Overflow(op, l, r) => {
61                         Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?)
62                     }
63                     OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?),
64                     DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?),
65                     RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?),
66                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
67                 };
68                 Assert { cond: cond.try_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, cleanup } => {
80                 InlineAsm {
81                     template,
82                     operands: operands.try_fold_with(folder)?,
83                     options,
84                     line_spans,
85                     destination,
86                     cleanup,
87                 }
88             }
89         };
90         Ok(Terminator { source_info: self.source_info, kind })
91     }
92 }
93
94 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
95     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
96         Ok(self)
97     }
98 }
99
100 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
101     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
102         Ok(Place {
103             local: self.local.try_fold_with(folder)?,
104             projection: self.projection.try_fold_with(folder)?,
105         })
106     }
107 }
108
109 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
110     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
111         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
112     }
113 }
114
115 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
116     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
117         use crate::mir::Rvalue::*;
118         Ok(match self {
119             Use(op) => Use(op.try_fold_with(folder)?),
120             Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?),
121             ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?),
122             Ref(region, bk, place) => {
123                 Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?)
124             }
125             CopyForDeref(place) => CopyForDeref(place.try_fold_with(folder)?),
126             AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?),
127             Len(place) => Len(place.try_fold_with(folder)?),
128             Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?),
129             BinaryOp(op, box (rhs, lhs)) => {
130                 BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)))
131             }
132             CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp(
133                 op,
134                 Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)),
135             ),
136             UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?),
137             Discriminant(place) => Discriminant(place.try_fold_with(folder)?),
138             NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?),
139             Aggregate(kind, fields) => {
140                 let kind = kind.try_map_id(|kind| {
141                     Ok(match kind {
142                         AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?),
143                         AggregateKind::Tuple => AggregateKind::Tuple,
144                         AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
145                             def,
146                             v,
147                             substs.try_fold_with(folder)?,
148                             user_ty.try_fold_with(folder)?,
149                             n,
150                         ),
151                         AggregateKind::Closure(id, substs) => {
152                             AggregateKind::Closure(id, substs.try_fold_with(folder)?)
153                         }
154                         AggregateKind::Generator(id, substs, movablity) => {
155                             AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
156                         }
157                     })
158                 })?;
159                 Aggregate(kind, fields.try_fold_with(folder)?)
160             }
161             ShallowInitBox(op, ty) => {
162                 ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
163             }
164         })
165     }
166 }
167
168 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
169     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
170         Ok(match self {
171             Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?),
172             Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?),
173             Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
174         })
175     }
176 }
177
178 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
179     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
180         use crate::mir::ProjectionElem::*;
181
182         Ok(match self {
183             Deref => Deref,
184             Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
185             Index(v) => Index(v.try_fold_with(folder)?),
186             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
187             ConstantIndex { offset, min_length, from_end } => {
188                 ConstantIndex { offset, min_length, from_end }
189             }
190             Subslice { from, to, from_end } => Subslice { from, to, from_end },
191         })
192     }
193 }
194
195 impl<'tcx> TypeFoldable<'tcx> for Field {
196     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
197         Ok(self)
198     }
199 }
200
201 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
202     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
203         Ok(self)
204     }
205 }
206
207 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
208     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
209         Ok(self)
210     }
211 }
212
213 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
214     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
215         Ok(Constant {
216             span: self.span,
217             user_ty: self.user_ty.try_fold_with(folder)?,
218             literal: self.literal.try_fold_with(folder)?,
219         })
220     }
221 }
222
223 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
224     #[inline(always)]
225     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
226         folder.try_fold_mir_const(self)
227     }
228 }
229
230 impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
231     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
232         self,
233         folder: &mut F,
234     ) -> Result<Self, F::Error> {
235         match self {
236             ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
237             ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
238         }
239     }
240 }