]> git.proxmox.com Git - rustc.git/blob - src/librustc_middle/mir/type_foldable.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / 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 SourceScopeData,
14 SourceScopeLocalData,
15 UserTypeAnnotationIndex,
16 }
17
18 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
19 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
20 use crate::mir::TerminatorKind::*;
21
22 let kind = match self.kind {
23 Goto { target } => Goto { target },
24 SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
25 discr: discr.fold_with(folder),
26 switch_ty: switch_ty.fold_with(folder),
27 values: values.clone(),
28 targets: targets.clone(),
29 },
30 Drop { ref place, target, unwind } => {
31 Drop { place: place.fold_with(folder), target, unwind }
32 }
33 DropAndReplace { ref place, ref value, target, unwind } => DropAndReplace {
34 place: place.fold_with(folder),
35 value: value.fold_with(folder),
36 target,
37 unwind,
38 },
39 Yield { ref value, resume, ref resume_arg, drop } => Yield {
40 value: value.fold_with(folder),
41 resume,
42 resume_arg: resume_arg.fold_with(folder),
43 drop,
44 },
45 Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
46 let dest =
47 destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
48
49 Call {
50 func: func.fold_with(folder),
51 args: args.fold_with(folder),
52 destination: dest,
53 cleanup,
54 from_hir_call,
55 fn_span,
56 }
57 }
58 Assert { ref cond, expected, ref msg, target, cleanup } => {
59 use AssertKind::*;
60 let msg = match msg {
61 BoundsCheck { len, index } => {
62 BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
63 }
64 Overflow(op, l, r) => Overflow(*op, l.fold_with(folder), r.fold_with(folder)),
65 OverflowNeg(op) => OverflowNeg(op.fold_with(folder)),
66 DivisionByZero(op) => DivisionByZero(op.fold_with(folder)),
67 RemainderByZero(op) => RemainderByZero(op.fold_with(folder)),
68 ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg.clone(),
69 };
70 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
71 }
72 GeneratorDrop => GeneratorDrop,
73 Resume => Resume,
74 Abort => Abort,
75 Return => Return,
76 Unreachable => Unreachable,
77 FalseEdge { real_target, imaginary_target } => {
78 FalseEdge { real_target, imaginary_target }
79 }
80 FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
81 InlineAsm { template, ref operands, options, line_spans, destination } => InlineAsm {
82 template,
83 operands: operands.fold_with(folder),
84 options,
85 line_spans,
86 destination,
87 },
88 };
89 Terminator { source_info: self.source_info, kind }
90 }
91
92 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
93 use crate::mir::TerminatorKind::*;
94
95 match self.kind {
96 SwitchInt { ref discr, switch_ty, .. } => {
97 discr.visit_with(visitor) || switch_ty.visit_with(visitor)
98 }
99 Drop { ref place, .. } => place.visit_with(visitor),
100 DropAndReplace { ref place, ref value, .. } => {
101 place.visit_with(visitor) || value.visit_with(visitor)
102 }
103 Yield { ref value, .. } => value.visit_with(visitor),
104 Call { ref func, ref args, ref destination, .. } => {
105 let dest = if let Some((ref loc, _)) = *destination {
106 loc.visit_with(visitor)
107 } else {
108 false
109 };
110 dest || func.visit_with(visitor) || args.visit_with(visitor)
111 }
112 Assert { ref cond, ref msg, .. } => {
113 if cond.visit_with(visitor) {
114 use AssertKind::*;
115 match msg {
116 BoundsCheck { ref len, ref index } => {
117 len.visit_with(visitor) || index.visit_with(visitor)
118 }
119 Overflow(_, l, r) => l.visit_with(visitor) || r.visit_with(visitor),
120 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
121 op.visit_with(visitor)
122 }
123 ResumedAfterReturn(_) | ResumedAfterPanic(_) => false,
124 }
125 } else {
126 false
127 }
128 }
129 InlineAsm { ref operands, .. } => operands.visit_with(visitor),
130 Goto { .. }
131 | Resume
132 | Abort
133 | Return
134 | GeneratorDrop
135 | Unreachable
136 | FalseEdge { .. }
137 | FalseUnwind { .. } => false,
138 }
139 }
140 }
141
142 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
143 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
144 *self
145 }
146
147 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
148 false
149 }
150 }
151
152 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
153 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
154 Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
155 }
156
157 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
158 self.local.visit_with(visitor) || self.projection.visit_with(visitor)
159 }
160 }
161
162 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
163 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
164 let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
165 folder.tcx().intern_place_elems(&v)
166 }
167
168 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
169 self.iter().any(|t| t.visit_with(visitor))
170 }
171 }
172
173 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
174 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
175 use crate::mir::Rvalue::*;
176 match *self {
177 Use(ref op) => Use(op.fold_with(folder)),
178 Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
179 ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
180 Ref(region, bk, ref place) => {
181 Ref(region.fold_with(folder), bk, place.fold_with(folder))
182 }
183 AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)),
184 Len(ref place) => Len(place.fold_with(folder)),
185 Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
186 BinaryOp(op, ref rhs, ref lhs) => {
187 BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
188 }
189 CheckedBinaryOp(op, ref rhs, ref lhs) => {
190 CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
191 }
192 UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
193 Discriminant(ref place) => Discriminant(place.fold_with(folder)),
194 NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
195 Aggregate(ref kind, ref fields) => {
196 let kind = box match **kind {
197 AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
198 AggregateKind::Tuple => AggregateKind::Tuple,
199 AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
200 def,
201 v,
202 substs.fold_with(folder),
203 user_ty.fold_with(folder),
204 n,
205 ),
206 AggregateKind::Closure(id, substs) => {
207 AggregateKind::Closure(id, substs.fold_with(folder))
208 }
209 AggregateKind::Generator(id, substs, movablity) => {
210 AggregateKind::Generator(id, substs.fold_with(folder), movablity)
211 }
212 };
213 Aggregate(kind, fields.fold_with(folder))
214 }
215 }
216 }
217
218 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
219 use crate::mir::Rvalue::*;
220 match *self {
221 Use(ref op) => op.visit_with(visitor),
222 Repeat(ref op, _) => op.visit_with(visitor),
223 ThreadLocalRef(did) => did.visit_with(visitor),
224 Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
225 AddressOf(_, ref place) => place.visit_with(visitor),
226 Len(ref place) => place.visit_with(visitor),
227 Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
228 BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
229 rhs.visit_with(visitor) || lhs.visit_with(visitor)
230 }
231 UnaryOp(_, ref val) => val.visit_with(visitor),
232 Discriminant(ref place) => place.visit_with(visitor),
233 NullaryOp(_, ty) => ty.visit_with(visitor),
234 Aggregate(ref kind, ref fields) => {
235 (match **kind {
236 AggregateKind::Array(ty) => ty.visit_with(visitor),
237 AggregateKind::Tuple => false,
238 AggregateKind::Adt(_, _, substs, user_ty, _) => {
239 substs.visit_with(visitor) || user_ty.visit_with(visitor)
240 }
241 AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
242 AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
243 }) || fields.visit_with(visitor)
244 }
245 }
246 }
247 }
248
249 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
250 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
251 match *self {
252 Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
253 Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
254 Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
255 }
256 }
257
258 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
259 match *self {
260 Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
261 Operand::Constant(ref c) => c.visit_with(visitor),
262 }
263 }
264 }
265
266 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
267 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
268 use crate::mir::ProjectionElem::*;
269
270 match *self {
271 Deref => Deref,
272 Field(f, ty) => Field(f, ty.fold_with(folder)),
273 Index(v) => Index(v.fold_with(folder)),
274 Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
275 ConstantIndex { offset, min_length, from_end } => {
276 ConstantIndex { offset, min_length, from_end }
277 }
278 Subslice { from, to, from_end } => Subslice { from, to, from_end },
279 }
280 }
281
282 fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
283 use crate::mir::ProjectionElem::*;
284
285 match self {
286 Field(_, ty) => ty.visit_with(visitor),
287 Index(v) => v.visit_with(visitor),
288 _ => false,
289 }
290 }
291 }
292
293 impl<'tcx> TypeFoldable<'tcx> for Field {
294 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
295 *self
296 }
297 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
298 false
299 }
300 }
301
302 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
303 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
304 *self
305 }
306 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
307 false
308 }
309 }
310
311 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
312 fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
313 self.clone()
314 }
315 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
316 false
317 }
318 }
319
320 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
321 fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
322 Constant {
323 span: self.span,
324 user_ty: self.user_ty.fold_with(folder),
325 literal: self.literal.fold_with(folder),
326 }
327 }
328 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
329 self.literal.visit_with(visitor)
330 }
331 }