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