type_foldable.rs 14.1 KB
Newer Older
1 2 3 4
//! `TypeFoldable` implementations for MIR types

use super::*;
use crate::ty;
B
Bastian Kauschke 已提交
5
use rustc_data_structures::functor::IdFunctor;
6

L
words  
lcnr 已提交
7
TrivialTypeFoldableAndLiftImpls! {
8 9 10 11 12 13 14 15 16 17 18
    BlockTailInfo,
    MirPhase,
    SourceInfo,
    FakeReadCause,
    RetagKind,
    SourceScope,
    SourceScopeLocalData,
    UserTypeAnnotationIndex,
}

impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
B
Bastian Kauschke 已提交
19
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
20 21 22 23
        use crate::mir::TerminatorKind::*;

        let kind = match self.kind {
            Goto { target } => Goto { target },
B
Bastian Kauschke 已提交
24
            SwitchInt { discr, switch_ty, targets } => SwitchInt {
25 26
                discr: discr.fold_with(folder),
                switch_ty: switch_ty.fold_with(folder),
L
words  
lcnr 已提交
27
                targets,
28
            },
B
Bastian Kauschke 已提交
29
            Drop { place, target, unwind } => {
30
                Drop { place: place.fold_with(folder), target, unwind }
31
            }
B
Bastian Kauschke 已提交
32
            DropAndReplace { place, value, target, unwind } => DropAndReplace {
33
                place: place.fold_with(folder),
34 35 36 37
                value: value.fold_with(folder),
                target,
                unwind,
            },
B
Bastian Kauschke 已提交
38
            Yield { value, resume, resume_arg, drop } => Yield {
39 40 41 42 43
                value: value.fold_with(folder),
                resume,
                resume_arg: resume_arg.fold_with(folder),
                drop,
            },
B
Bastian Kauschke 已提交
44
            Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
L
words  
lcnr 已提交
45
                let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest));
46 47 48 49 50 51 52

                Call {
                    func: func.fold_with(folder),
                    args: args.fold_with(folder),
                    destination: dest,
                    cleanup,
                    from_hir_call,
53
                    fn_span,
54 55
                }
            }
B
Bastian Kauschke 已提交
56
            Assert { cond, expected, msg, target, cleanup } => {
57 58
                use AssertKind::*;
                let msg = match msg {
59
                    BoundsCheck { len, index } => {
60 61
                        BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
                    }
B
Bastian Kauschke 已提交
62
                    Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)),
63 64 65
                    OverflowNeg(op) => OverflowNeg(op.fold_with(folder)),
                    DivisionByZero(op) => DivisionByZero(op.fold_with(folder)),
                    RemainderByZero(op) => RemainderByZero(op.fold_with(folder)),
L
words  
lcnr 已提交
66
                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
67 68 69 70 71 72 73 74
                };
                Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
            }
            GeneratorDrop => GeneratorDrop,
            Resume => Resume,
            Abort => Abort,
            Return => Return,
            Unreachable => Unreachable,
R
Ralf Jung 已提交
75 76
            FalseEdge { real_target, imaginary_target } => {
                FalseEdge { real_target, imaginary_target }
77 78
            }
            FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
B
Bastian Kauschke 已提交
79
            InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
80 81 82 83 84 85
                template,
                operands: operands.fold_with(folder),
                options,
                line_spans,
                destination,
            },
86 87 88 89
        };
        Terminator { source_info: self.source_info, kind }
    }

L
LeSeulArtichaut 已提交
90
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
91 92 93 94
        use crate::mir::TerminatorKind::*;

        match self.kind {
            SwitchInt { ref discr, switch_ty, .. } => {
95 96
                discr.visit_with(visitor)?;
                switch_ty.visit_with(visitor)
97
            }
98 99
            Drop { ref place, .. } => place.visit_with(visitor),
            DropAndReplace { ref place, ref value, .. } => {
100 101
                place.visit_with(visitor)?;
                value.visit_with(visitor)
102 103 104
            }
            Yield { ref value, .. } => value.visit_with(visitor),
            Call { ref func, ref args, ref destination, .. } => {
105 106
                if let Some((ref loc, _)) = *destination {
                    loc.visit_with(visitor)?;
107
                };
108 109
                func.visit_with(visitor)?;
                args.visit_with(visitor)
110 111
            }
            Assert { ref cond, ref msg, .. } => {
112 113 114 115 116 117 118 119 120 121 122 123 124
                cond.visit_with(visitor)?;
                use AssertKind::*;
                match msg {
                    BoundsCheck { ref len, ref index } => {
                        len.visit_with(visitor)?;
                        index.visit_with(visitor)
                    }
                    Overflow(_, l, r) => {
                        l.visit_with(visitor)?;
                        r.visit_with(visitor)
                    }
                    OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
                        op.visit_with(visitor)
125
                    }
126
                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
127 128
                }
            }
A
Amanieu d'Antras 已提交
129
            InlineAsm { ref operands, .. } => operands.visit_with(visitor),
130 131 132 133 134 135
            Goto { .. }
            | Resume
            | Abort
            | Return
            | GeneratorDrop
            | Unreachable
R
Ralf Jung 已提交
136
            | FalseEdge { .. }
137
            | FalseUnwind { .. } => ControlFlow::CONTINUE,
138 139 140 141 142
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
B
Bastian Kauschke 已提交
143 144
    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
        self
145 146
    }

L
LeSeulArtichaut 已提交
147
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
148
        ControlFlow::CONTINUE
149 150 151 152
    }
}

impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
B
Bastian Kauschke 已提交
153
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
154 155 156
        Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
    }

L
LeSeulArtichaut 已提交
157
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
158 159
        self.local.visit_with(visitor)?;
        self.projection.visit_with(visitor)
160 161 162 163
    }
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
B
Bastian Kauschke 已提交
164
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
L
words  
lcnr 已提交
165
        ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
166 167
    }

L
LeSeulArtichaut 已提交
168
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
169
        self.iter().try_for_each(|t| t.visit_with(visitor))
170 171 172 173
    }
}

impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
B
Bastian Kauschke 已提交
174
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
175
        use crate::mir::Rvalue::*;
B
Bastian Kauschke 已提交
176 177 178
        match self {
            Use(op) => Use(op.fold_with(folder)),
            Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
179
            ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
B
Bastian Kauschke 已提交
180 181 182 183
            Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)),
            AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)),
            Len(place) => Len(place.fold_with(folder)),
            Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
184 185 186 187 188
            BinaryOp(op, box (rhs, lhs)) => {
                BinaryOp(op, box (rhs.fold_with(folder), lhs.fold_with(folder)))
            }
            CheckedBinaryOp(op, box (rhs, lhs)) => {
                CheckedBinaryOp(op, box (rhs.fold_with(folder), lhs.fold_with(folder)))
189
            }
B
Bastian Kauschke 已提交
190 191
            UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)),
            Discriminant(place) => Discriminant(place.fold_with(folder)),
192
            NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
B
Bastian Kauschke 已提交
193 194
            Aggregate(kind, fields) => {
                let kind = kind.map_id(|kind| match kind {
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
                    AggregateKind::Tuple => AggregateKind::Tuple,
                    AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
                        def,
                        v,
                        substs.fold_with(folder),
                        user_ty.fold_with(folder),
                        n,
                    ),
                    AggregateKind::Closure(id, substs) => {
                        AggregateKind::Closure(id, substs.fold_with(folder))
                    }
                    AggregateKind::Generator(id, substs, movablity) => {
                        AggregateKind::Generator(id, substs.fold_with(folder), movablity)
                    }
B
Bastian Kauschke 已提交
210
                });
211 212 213 214 215
                Aggregate(kind, fields.fold_with(folder))
            }
        }
    }

L
LeSeulArtichaut 已提交
216
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
217 218 219 220
        use crate::mir::Rvalue::*;
        match *self {
            Use(ref op) => op.visit_with(visitor),
            Repeat(ref op, _) => op.visit_with(visitor),
221
            ThreadLocalRef(did) => did.visit_with(visitor),
222 223 224 225
            Ref(region, _, ref place) => {
                region.visit_with(visitor)?;
                place.visit_with(visitor)
            }
226 227
            AddressOf(_, ref place) => place.visit_with(visitor),
            Len(ref place) => place.visit_with(visitor),
228 229 230 231
            Cast(_, ref op, ty) => {
                op.visit_with(visitor)?;
                ty.visit_with(visitor)
            }
232
            BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
233 234
                rhs.visit_with(visitor)?;
                lhs.visit_with(visitor)
235 236 237 238 239
            }
            UnaryOp(_, ref val) => val.visit_with(visitor),
            Discriminant(ref place) => place.visit_with(visitor),
            NullaryOp(_, ty) => ty.visit_with(visitor),
            Aggregate(ref kind, ref fields) => {
240 241 242 243 244
                match **kind {
                    AggregateKind::Array(ty) => {
                        ty.visit_with(visitor)?;
                    }
                    AggregateKind::Tuple => {}
245
                    AggregateKind::Adt(_, _, substs, user_ty, _) => {
246 247 248 249 250
                        substs.visit_with(visitor)?;
                        user_ty.visit_with(visitor)?;
                    }
                    AggregateKind::Closure(_, substs) => {
                        substs.visit_with(visitor)?;
251
                    }
252 253 254 255 256
                    AggregateKind::Generator(_, substs, _) => {
                        substs.visit_with(visitor)?;
                    }
                }
                fields.visit_with(visitor)
257 258 259 260 261 262
            }
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
B
Bastian Kauschke 已提交
263 264 265 266 267
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
        match self {
            Operand::Copy(place) => Operand::Copy(place.fold_with(folder)),
            Operand::Move(place) => Operand::Move(place.fold_with(folder)),
            Operand::Constant(c) => Operand::Constant(c.fold_with(folder)),
268 269 270
        }
    }

L
LeSeulArtichaut 已提交
271
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
272 273 274 275 276 277 278 279
        match *self {
            Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
            Operand::Constant(ref c) => c.visit_with(visitor),
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
B
Bastian Kauschke 已提交
280
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
281 282
        use crate::mir::ProjectionElem::*;

B
Bastian Kauschke 已提交
283
        match self {
284 285 286 287 288 289 290 291 292 293 294
            Deref => Deref,
            Field(f, ty) => Field(f, ty.fold_with(folder)),
            Index(v) => Index(v.fold_with(folder)),
            Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
            ConstantIndex { offset, min_length, from_end } => {
                ConstantIndex { offset, min_length, from_end }
            }
            Subslice { from, to, from_end } => Subslice { from, to, from_end },
        }
    }

L
LeSeulArtichaut 已提交
295 296 297 298
    fn super_visit_with<Vs: TypeVisitor<'tcx>>(
        &self,
        visitor: &mut Vs,
    ) -> ControlFlow<Vs::BreakTy> {
299 300 301 302 303
        use crate::mir::ProjectionElem::*;

        match self {
            Field(_, ty) => ty.visit_with(visitor),
            Index(v) => v.visit_with(visitor),
304
            _ => ControlFlow::CONTINUE,
305 306 307 308 309
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for Field {
B
Bastian Kauschke 已提交
310 311
    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
        self
312
    }
L
LeSeulArtichaut 已提交
313
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
314
        ControlFlow::CONTINUE
315 316 317 318
    }
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
B
Bastian Kauschke 已提交
319 320
    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
        self
321
    }
L
LeSeulArtichaut 已提交
322
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
323
        ControlFlow::CONTINUE
324 325 326 327
    }
}

impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
B
Bastian Kauschke 已提交
328
    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
L
words  
lcnr 已提交
329
        self
330
    }
L
LeSeulArtichaut 已提交
331
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
332
        ControlFlow::CONTINUE
333 334 335 336
    }
}

impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
B
Bastian Kauschke 已提交
337
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
338 339 340 341 342 343
        Constant {
            span: self.span,
            user_ty: self.user_ty.fold_with(folder),
            literal: self.literal.fold_with(folder),
        }
    }
L
LeSeulArtichaut 已提交
344
    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
345 346
        self.literal.visit_with(visitor)?;
        self.user_ty.visit_with(visitor)
347 348 349
    }
}

O
Oli Scherer 已提交
350
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
351 352 353 354
    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
        folder.fold_mir_const(self)
    }

355 356
    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
        match self {
O
Oli Scherer 已提交
357 358
            ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
            ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)),
359 360 361 362 363
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
        match *self {
O
Oli Scherer 已提交
364 365
            ConstantKind::Ty(c) => c.visit_with(visitor),
            ConstantKind::Val(_, t) => t.visit_with(visitor),
366
        }
367 368
    }
}