visit.rs 39.9 KB
Newer Older
N
Niko Matsakis 已提交
1 2 3 4 5 6 7 8 9 10
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use hir::def_id::DefId;
12
use ty::subst::Substs;
13
use ty::{CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty};
E
Eduard Burtescu 已提交
14
use mir::*;
15
use syntax_pos::Span;
N
Niko Matsakis 已提交
16

N
Niko Matsakis 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// # The MIR Visitor
//
// ## Overview
//
// There are two visitors, one for immutable and one for mutable references,
// but both are generated by the following macro. The code is written according
// to the following conventions:
//
// - introduce a `visit_foo` and a `super_foo` method for every MIR type
// - `visit_foo`, by default, calls `super_foo`
// - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
//
// This allows you as a user to override `visit_foo` for types are
// interested in, and invoke (within that method) call
// `self.super_foo` to get the default behavior. Just as in an OO
// language, you should never call `super` methods ordinarily except
// in that circumstance.
//
// For the most part, we do not destructure things external to the
// MIR, e.g. types, spans, etc, but simply visit them and stop. This
37
// avoids duplication with other visitors like `TypeFoldable`.
N
Niko Matsakis 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
//
// ## Updating
//
// The code is written in a very deliberate style intended to minimize
// the chance of things being overlooked. You'll notice that we always
// use pattern matching to reference fields and we ensure that all
// matches are exhaustive.
//
// For example, the `super_basic_block_data` method begins like this:
//
// ```rust
// fn super_basic_block_data(&mut self,
//                           block: BasicBlock,
//                           data: & $($mutability)* BasicBlockData<'tcx>) {
//     let BasicBlockData {
//         ref $($mutability)* statements,
//         ref $($mutability)* terminator,
//         is_cleanup: _
//     } = *data;
//
//     for statement in statements {
//         self.visit_statement(block, statement);
//     }
//
//     ...
// }
// ```
//
// Here we used `let BasicBlockData { <fields> } = *data` deliberately,
// rather than writing `data.statements` in the body. This is because if one
// adds a new field to `BasicBlockData`, one will be forced to revise this code,
// and hence one will (hopefully) invoke the correct visit methods (if any).
//
// For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
// That means you never write `..` to skip over fields, nor do you write `_`
// to skip over variants in a `match`.
//
// The only place that `_` is acceptable is to match a field (or
// variant argument) that does not require visiting, as in
// `is_cleanup` above.

79 80 81 82 83
macro_rules! make_mir_visitor {
    ($visitor_trait_name:ident, $($mutability:ident)*) => {
        pub trait $visitor_trait_name<'tcx> {
            // Override these, and call `self.super_xxx` to revert back to the
            // default behavior.
N
Niko Matsakis 已提交
84

85 86
            fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
                self.super_mir(mir);
N
Niko Matsakis 已提交
87 88
            }

89 90 91 92
            fn visit_basic_block_data(&mut self,
                                      block: BasicBlock,
                                      data: & $($mutability)* BasicBlockData<'tcx>) {
                self.super_basic_block_data(block, data);
N
Niko Matsakis 已提交
93 94
            }

95 96 97
            fn visit_source_scope_data(&mut self,
                                           scope_data: & $($mutability)* SourceScopeData) {
                self.super_source_scope_data(scope_data);
N
Niko Matsakis 已提交
98 99
            }

100 101
            fn visit_statement(&mut self,
                               block: BasicBlock,
102 103 104
                               statement: & $($mutability)* Statement<'tcx>,
                               location: Location) {
                self.super_statement(block, statement, location);
N
Niko Matsakis 已提交
105 106
            }

107 108
            fn visit_assign(&mut self,
                            block: BasicBlock,
109
                            place: & $($mutability)* Place<'tcx>,
110 111
                            rvalue: & $($mutability)* Rvalue<'tcx>,
                            location: Location) {
112
                self.super_assign(block, place, rvalue, location);
N
Niko Matsakis 已提交
113 114
            }

115 116
            fn visit_terminator(&mut self,
                                block: BasicBlock,
117 118 119
                                terminator: & $($mutability)* Terminator<'tcx>,
                                location: Location) {
                self.super_terminator(block, terminator, location);
120 121
            }

N
Niko Matsakis 已提交
122 123
            fn visit_terminator_kind(&mut self,
                                     block: BasicBlock,
124 125 126
                                     kind: & $($mutability)* TerminatorKind<'tcx>,
                                     location: Location) {
                self.super_terminator_kind(block, kind, location);
N
Niko Matsakis 已提交
127 128
            }

129
            fn visit_assert_message(&mut self,
130 131 132
                                    msg: & $($mutability)* AssertMessage<'tcx>,
                                    location: Location) {
                self.super_assert_message(msg, location);
133 134
            }

135
            fn visit_rvalue(&mut self,
136 137 138
                            rvalue: & $($mutability)* Rvalue<'tcx>,
                            location: Location) {
                self.super_rvalue(rvalue, location);
N
Niko Matsakis 已提交
139 140
            }

141
            fn visit_operand(&mut self,
142 143 144
                             operand: & $($mutability)* Operand<'tcx>,
                             location: Location) {
                self.super_operand(operand, location);
145
            }
N
Niko Matsakis 已提交
146

147 148 149 150 151
            fn visit_ascribe_user_ty(&mut self,
                                     place: & $($mutability)* Place<'tcx>,
                                     c_ty: & $($mutability)* CanonicalTy<'tcx>,
                                     location: Location) {
                self.super_ascribe_user_ty(place, c_ty, location);
D
David Wood 已提交
152 153
            }

154 155
            fn visit_place(&mut self,
                            place: & $($mutability)* Place<'tcx>,
156
                            context: PlaceContext<'tcx>,
157
                            location: Location) {
158
                self.super_place(place, context, location);
N
Niko Matsakis 已提交
159 160
            }

161 162
            fn visit_static(&mut self,
                            static_: & $($mutability)* Static<'tcx>,
163
                            context: PlaceContext<'tcx>,
164 165 166 167
                            location: Location) {
                self.super_static(static_, context, location);
            }

N
Niko Matsakis 已提交
168
            fn visit_projection(&mut self,
169
                                place: & $($mutability)* PlaceProjection<'tcx>,
170
                                context: PlaceContext<'tcx>,
171
                                location: Location) {
172
                self.super_projection(place, context, location);
N
Niko Matsakis 已提交
173 174 175
            }

            fn visit_projection_elem(&mut self,
176
                                     place: & $($mutability)* PlaceElem<'tcx>,
177
                                     context: PlaceContext<'tcx>,
178
                                     location: Location) {
179
                self.super_projection_elem(place, context, location);
N
Niko Matsakis 已提交
180 181
            }

182 183 184 185
            fn visit_branch(&mut self,
                            source: BasicBlock,
                            target: BasicBlock) {
                self.super_branch(source, target);
N
Niko Matsakis 已提交
186 187
            }

188
            fn visit_constant(&mut self,
189 190 191
                              constant: & $($mutability)* Constant<'tcx>,
                              location: Location) {
                self.super_constant(constant, location);
N
Niko Matsakis 已提交
192 193
            }

194
            fn visit_def_id(&mut self,
195 196
                            def_id: & $($mutability)* DefId,
                            _: Location) {
197
                self.super_def_id(def_id);
N
Niko Matsakis 已提交
198 199
            }

200 201 202
            fn visit_span(&mut self,
                          span: & $($mutability)* Span) {
                self.super_span(span);
N
Niko Matsakis 已提交
203 204
            }

205 206 207 208 209
            fn visit_source_info(&mut self,
                                 source_info: & $($mutability)* SourceInfo) {
                self.super_source_info(source_info);
            }

N
Niko Matsakis 已提交
210
            fn visit_ty(&mut self,
211
                        ty: & $($mutability)* Ty<'tcx>,
212
                        _: TyContext) {
N
Niko Matsakis 已提交
213 214 215
                self.super_ty(ty);
            }

216 217 218 219
            fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
                self.super_canonical_ty(ty);
            }

220 221 222 223 224 225 226 227 228 229 230 231
            fn visit_region(&mut self,
                            region: & $($mutability)* ty::Region<'tcx>,
                            _: Location) {
                self.super_region(region);
            }

            fn visit_const(&mut self,
                           constant: & $($mutability)* &'tcx ty::Const<'tcx>,
                           _: Location) {
                self.super_const(constant);
            }

N
Niko Matsakis 已提交
232
            fn visit_substs(&mut self,
233 234
                            substs: & $($mutability)* &'tcx Substs<'tcx>,
                            _: Location) {
N
Niko Matsakis 已提交
235 236 237 238
                self.super_substs(substs);
            }

            fn visit_closure_substs(&mut self,
239 240
                                    substs: & $($mutability)* ClosureSubsts<'tcx>,
                                    _: Location) {
N
Niko Matsakis 已提交
241 242 243
                self.super_closure_substs(substs);
            }

244 245
            fn visit_generator_substs(&mut self,
                                      substs: & $($mutability)* GeneratorSubsts<'tcx>,
246
                                    _: Location) {
247
                self.super_generator_substs(substs);
248 249
            }

250
            fn visit_local_decl(&mut self,
251
                                local: Local,
252
                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
253
                self.super_local_decl(local, local_decl);
N
Niko Matsakis 已提交
254 255
            }

J
John Kåre Alsaker 已提交
256
            fn visit_local(&mut self,
257
                            _local: & $($mutability)* Local,
258
                            _context: PlaceContext<'tcx>,
259
                            _location: Location) {
J
John Kåre Alsaker 已提交
260 261
            }

262 263 264
            fn visit_source_scope(&mut self,
                                      scope: & $($mutability)* SourceScope) {
                self.super_source_scope(scope);
N
Niko Matsakis 已提交
265 266
            }

267
            // The `super_xxx` methods comprise the default behavior and are
C
Carlos E. Garcia 已提交
268
            // not meant to be overridden.
N
Niko Matsakis 已提交
269

270 271
            fn super_mir(&mut self,
                         mir: & $($mutability)* Mir<'tcx>) {
272 273 274
                if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
                    self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
                        span: mir.span,
275
                        scope: OUTERMOST_SOURCE_SCOPE,
276 277 278
                    }));
                }

279 280 281 282 283 284 285 286 287
                // for best performance, we want to use an iterator rather
                // than a for-loop, to avoid calling Mir::invalidate for
                // each basic block.
                macro_rules! basic_blocks {
                    (mut) => (mir.basic_blocks_mut().iter_enumerated_mut());
                    () => (mir.basic_blocks().iter_enumerated());
                };
                for (bb, data) in basic_blocks!($($mutability)*) {
                    self.visit_basic_block_data(bb, data);
288
                }
N
Niko Matsakis 已提交
289

290 291
                for scope in &$($mutability)* mir.source_scopes {
                    self.visit_source_scope_data(scope);
N
Niko Matsakis 已提交
292 293
                }

L
loomaclin 已提交
294
                self.visit_ty(&$($mutability)* mir.return_ty(), TyContext::ReturnTy(SourceInfo {
295
                    span: mir.span,
296
                    scope: OUTERMOST_SOURCE_SCOPE,
N
Niko Matsakis 已提交
297
                }));
N
Niko Matsakis 已提交
298

299 300
                for local in mir.local_decls.indices() {
                    self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
N
Niko Matsakis 已提交
301 302
                }

303
                self.visit_span(&$($mutability)* mir.span);
N
Niko Matsakis 已提交
304 305
            }

306 307 308
            fn super_basic_block_data(&mut self,
                                      block: BasicBlock,
                                      data: & $($mutability)* BasicBlockData<'tcx>) {
N
Niko Matsakis 已提交
309 310 311 312 313 314
                let BasicBlockData {
                    ref $($mutability)* statements,
                    ref $($mutability)* terminator,
                    is_cleanup: _
                } = *data;

315
                let mut index = 0;
N
Niko Matsakis 已提交
316
                for statement in statements {
317 318 319
                    let location = Location { block: block, statement_index: index };
                    self.visit_statement(block, statement, location);
                    index += 1;
N
Niko Matsakis 已提交
320 321
                }

N
Niko Matsakis 已提交
322
                if let Some(ref $($mutability)* terminator) = *terminator {
323 324
                    let location = Location { block: block, statement_index: index };
                    self.visit_terminator(block, terminator, location);
325
                }
N
Niko Matsakis 已提交
326 327
            }

328 329 330
            fn super_source_scope_data(&mut self,
                                           scope_data: & $($mutability)* SourceScopeData) {
                let SourceScopeData {
331
                    ref $($mutability)* span,
N
Niko Matsakis 已提交
332 333 334
                    ref $($mutability)* parent_scope,
                } = *scope_data;

335
                self.visit_span(span);
N
Niko Matsakis 已提交
336
                if let Some(ref $($mutability)* parent_scope) = *parent_scope {
337
                    self.visit_source_scope(parent_scope);
N
Niko Matsakis 已提交
338 339 340
                }
            }

341 342
            fn super_statement(&mut self,
                               block: BasicBlock,
343 344
                               statement: & $($mutability)* Statement<'tcx>,
                               location: Location) {
N
Niko Matsakis 已提交
345
                let Statement {
346
                    ref $($mutability)* source_info,
N
Niko Matsakis 已提交
347 348 349
                    ref $($mutability)* kind,
                } = *statement;

350
                self.visit_source_info(source_info);
N
Niko Matsakis 已提交
351
                match *kind {
352
                    StatementKind::Assign(ref $($mutability)* place,
353
                                          ref $($mutability)* rvalue) => {
354
                        self.visit_assign(block, place, rvalue, location);
355
                    }
356 357 358 359 360
                    StatementKind::ReadForMatch(ref $($mutability)* place) => {
                        self.visit_place(place,
                                         PlaceContext::Inspect,
                                         location);
                    }
361
                    StatementKind::EndRegion(_) => {}
362 363 364
                    StatementKind::Validate(_, ref $($mutability)* places) => {
                        for operand in places {
                            self.visit_place(& $($mutability)* operand.place,
365
                                              PlaceContext::Validate, location);
366 367
                            self.visit_ty(& $($mutability)* operand.ty,
                                          TyContext::Location(location));
368 369
                        }
                    }
370 371
                    StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
                        self.visit_place(place, PlaceContext::Store, location);
372
                    }
373
                    StatementKind::StorageLive(ref $($mutability)* local) => {
374
                        self.visit_local(local, PlaceContext::StorageLive, location);
375
                    }
376
                    StatementKind::StorageDead(ref $($mutability)* local) => {
377
                        self.visit_local(local, PlaceContext::StorageDead, location);
378
                    }
379 380 381 382
                    StatementKind::InlineAsm { ref $($mutability)* outputs,
                                               ref $($mutability)* inputs,
                                               asm: _ } => {
                        for output in & $($mutability)* outputs[..] {
383
                            self.visit_place(output, PlaceContext::AsmOutput, location);
384 385 386 387 388
                        }
                        for input in & $($mutability)* inputs[..] {
                            self.visit_operand(input, location);
                        }
                    }
389 390 391 392 393
                    StatementKind::AscribeUserType(
                        ref $($mutability)* place,
                        ref $($mutability)* c_ty,
                    ) => {
                        self.visit_ascribe_user_ty(place, c_ty, location);
D
David Wood 已提交
394
                    }
395
                    StatementKind::Nop => {}
396
                }
N
Niko Matsakis 已提交
397
            }
398

399 400
            fn super_assign(&mut self,
                            _block: BasicBlock,
401
                            place: &$($mutability)* Place<'tcx>,
402 403
                            rvalue: &$($mutability)* Rvalue<'tcx>,
                            location: Location) {
404
                self.visit_place(place, PlaceContext::Store, location);
405
                self.visit_rvalue(rvalue, location);
406
            }
407

408 409
            fn super_terminator(&mut self,
                                block: BasicBlock,
410 411
                                terminator: &$($mutability)* Terminator<'tcx>,
                                location: Location) {
N
Niko Matsakis 已提交
412
                let Terminator {
413
                    ref $($mutability)* source_info,
N
Niko Matsakis 已提交
414 415 416
                    ref $($mutability)* kind,
                } = *terminator;

417
                self.visit_source_info(source_info);
418
                self.visit_terminator_kind(block, kind, location);
N
Niko Matsakis 已提交
419 420 421 422
            }

            fn super_terminator_kind(&mut self,
                                     block: BasicBlock,
423 424
                                     kind: & $($mutability)* TerminatorKind<'tcx>,
                                     source_location: Location) {
N
Niko Matsakis 已提交
425
                match *kind {
426
                    TerminatorKind::Goto { target } => {
427 428
                        self.visit_branch(block, target);
                    }
429

430
                    TerminatorKind::SwitchInt { ref $($mutability)* discr,
N
Niko Matsakis 已提交
431
                                                ref $($mutability)* switch_ty,
O
Oliver Schneider 已提交
432
                                                values: _,
433
                                                ref targets } => {
434
                        self.visit_operand(discr, source_location);
435
                        self.visit_ty(switch_ty, TyContext::Location(source_location));
436 437 438 439
                        for &target in targets {
                            self.visit_branch(block, target);
                        }
                    }
440

441
                    TerminatorKind::Resume |
D
David Henningsson 已提交
442
                    TerminatorKind::Abort |
A
Alex Crichton 已提交
443
                    TerminatorKind::Return |
J
John Kåre Alsaker 已提交
444
                    TerminatorKind::GeneratorDrop |
445
                    TerminatorKind::Unreachable => {
446
                    }
447

448
                    TerminatorKind::Drop { ref $($mutability)* location,
449 450
                                           target,
                                           unwind } => {
451
                        self.visit_place(location, PlaceContext::Drop, source_location);
452 453 454 455 456 457 458 459
                        self.visit_branch(block, target);
                        unwind.map(|t| self.visit_branch(block, t));
                    }

                    TerminatorKind::DropAndReplace { ref $($mutability)* location,
                                                     ref $($mutability)* value,
                                                     target,
                                                     unwind } => {
460
                        self.visit_place(location, PlaceContext::Drop, source_location);
461
                        self.visit_operand(value, source_location);
462 463 464 465
                        self.visit_branch(block, target);
                        unwind.map(|t| self.visit_branch(block, t));
                    }

466 467 468 469
                    TerminatorKind::Call { ref $($mutability)* func,
                                           ref $($mutability)* args,
                                           ref $($mutability)* destination,
                                           cleanup } => {
470
                        self.visit_operand(func, source_location);
471
                        for arg in args {
472
                            self.visit_operand(arg, source_location);
473
                        }
S
Simonas Kazlauskas 已提交
474
                        if let Some((ref $($mutability)* destination, target)) = *destination {
475
                            self.visit_place(destination, PlaceContext::Call, source_location);
476 477
                            self.visit_branch(block, target);
                        }
S
Simonas Kazlauskas 已提交
478
                        cleanup.map(|t| self.visit_branch(block, t));
479
                    }
480 481 482 483 484 485

                    TerminatorKind::Assert { ref $($mutability)* cond,
                                             expected: _,
                                             ref $($mutability)* msg,
                                             target,
                                             cleanup } => {
486 487
                        self.visit_operand(cond, source_location);
                        self.visit_assert_message(msg, source_location);
488 489 490
                        self.visit_branch(block, target);
                        cleanup.map(|t| self.visit_branch(block, t));
                    }
J
John Kåre Alsaker 已提交
491

J
John Kåre Alsaker 已提交
492
                    TerminatorKind::Yield { ref $($mutability)* value,
J
John Kåre Alsaker 已提交
493 494 495 496 497 498 499
                                              resume,
                                              drop } => {
                        self.visit_operand(value, source_location);
                        self.visit_branch(block, resume);
                        drop.map(|t| self.visit_branch(block, t));
                    }

500
                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => {
501 502 503 504 505
                        self.visit_branch(block, real_target);
                        for target in imaginary_targets {
                            self.visit_branch(block, *target);
                        }
                    }
506 507 508 509 510 511 512

                    TerminatorKind::FalseUnwind { real_target, unwind } => {
                        self.visit_branch(block, real_target);
                        if let Some(unwind) = unwind {
                            self.visit_branch(block, unwind);
                        }
                    }
513 514 515 516
                }
            }

            fn super_assert_message(&mut self,
517 518
                                    msg: & $($mutability)* AssertMessage<'tcx>,
                                    location: Location) {
519 520
                use mir::interpret::EvalErrorKind::*;
                if let BoundsCheck {
521 522
                        ref $($mutability)* len,
                        ref $($mutability)* index
523 524 525
                    } = *msg {
                    self.visit_operand(len, location);
                    self.visit_operand(index, location);
526 527
                }
            }
528

529
            fn super_rvalue(&mut self,
530 531
                            rvalue: & $($mutability)* Rvalue<'tcx>,
                            location: Location) {
532 533
                match *rvalue {
                    Rvalue::Use(ref $($mutability)* operand) => {
534
                        self.visit_operand(operand, location);
535
                    }
536

O
Oliver Schneider 已提交
537
                    Rvalue::Repeat(ref $($mutability)* value, _) => {
538
                        self.visit_operand(value, location);
539
                    }
540

541 542
                    Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
                        self.visit_region(r, location);
543
                        self.visit_place(path, PlaceContext::Borrow {
544
                            region: *r,
545
                            kind: bk
546
                        }, location);
547
                    }
548

549
                    Rvalue::Len(ref $($mutability)* path) => {
550
                        self.visit_place(path, PlaceContext::Inspect, location);
551
                    }
552

N
Niko Matsakis 已提交
553 554 555
                    Rvalue::Cast(_cast_kind,
                                 ref $($mutability)* operand,
                                 ref $($mutability)* ty) => {
556
                        self.visit_operand(operand, location);
557
                        self.visit_ty(ty, TyContext::Location(location));
558
                    }
559

N
Niko Matsakis 已提交
560
                    Rvalue::BinaryOp(_bin_op,
J
James Miller 已提交
561 562 563
                                     ref $($mutability)* lhs,
                                     ref $($mutability)* rhs) |
                    Rvalue::CheckedBinaryOp(_bin_op,
564 565
                                     ref $($mutability)* lhs,
                                     ref $($mutability)* rhs) => {
566 567
                        self.visit_operand(lhs, location);
                        self.visit_operand(rhs, location);
568
                    }
569

N
Niko Matsakis 已提交
570
                    Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
571
                        self.visit_operand(op, location);
572
                    }
573

574 575
                    Rvalue::Discriminant(ref $($mutability)* place) => {
                        self.visit_place(place, PlaceContext::Inspect, location);
576 577
                    }

578
                    Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
579
                        self.visit_ty(ty, TyContext::Location(location));
580
                    }
581

582 583
                    Rvalue::Aggregate(ref $($mutability)* kind,
                                      ref $($mutability)* operands) => {
A
Ariel Ben-Yehuda 已提交
584
                        let kind = &$($mutability)* **kind;
585
                        match *kind {
S
Simonas Kazlauskas 已提交
586
                            AggregateKind::Array(ref $($mutability)* ty) => {
587
                                self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
588 589 590 591 592
                            }
                            AggregateKind::Tuple => {
                            }
                            AggregateKind::Adt(_adt_def,
                                               _variant_index,
593
                                               ref $($mutability)* substs,
N
Niko Matsakis 已提交
594
                                               _user_substs,
595
                                               _active_field_index) => {
596
                                self.visit_substs(substs, location);
N
Niko Matsakis 已提交
597 598 599
                            }
                            AggregateKind::Closure(ref $($mutability)* def_id,
                                                   ref $($mutability)* closure_substs) => {
600
                                self.visit_def_id(def_id, location);
601
                                self.visit_closure_substs(closure_substs, location);
602
                            }
J
John Kåre Alsaker 已提交
603
                            AggregateKind::Generator(ref $($mutability)* def_id,
604
                                                     ref $($mutability)* generator_substs,
605
                                                     _movability) => {
J
John Kåre Alsaker 已提交
606
                                self.visit_def_id(def_id, location);
607
                                self.visit_generator_substs(generator_substs, location);
J
John Kåre Alsaker 已提交
608
                            }
609 610
                        }

N
Niko Matsakis 已提交
611
                        for operand in operands {
612
                            self.visit_operand(operand, location);
613 614
                        }
                    }
615 616 617
                }
            }

618
            fn super_operand(&mut self,
619 620
                             operand: & $($mutability)* Operand<'tcx>,
                             location: Location) {
621
                match *operand {
622 623
                    Operand::Copy(ref $($mutability)* place) => {
                        self.visit_place(place, PlaceContext::Copy, location);
624
                    }
625 626
                    Operand::Move(ref $($mutability)* place) => {
                        self.visit_place(place, PlaceContext::Move, location);
627 628
                    }
                    Operand::Constant(ref $($mutability)* constant) => {
629
                        self.visit_constant(constant, location);
630
                    }
631 632 633
                }
            }

634 635 636 637 638
            fn super_ascribe_user_ty(&mut self,
                                     place: & $($mutability)* Place<'tcx>,
                                     c_ty: & $($mutability)* CanonicalTy<'tcx>,
                                     location: Location) {
                self.visit_place(place, PlaceContext::Validate, location);
639
                self.visit_canonical_ty(c_ty);
D
David Wood 已提交
640 641
            }

642 643
            fn super_place(&mut self,
                            place: & $($mutability)* Place<'tcx>,
644
                            context: PlaceContext<'tcx>,
645
                            location: Location) {
646
                match *place {
647
                    Place::Local(ref $($mutability)* local) => {
648
                        self.visit_local(local, context, location);
649
                    }
650
                    Place::Static(ref $($mutability)* static_) => {
651
                        self.visit_static(static_, context, location);
652
                    }
653 654 655
                    Place::Promoted(ref $($mutability)* promoted) => {
                        self.visit_ty(& $($mutability)* promoted.1, TyContext::Location(location));
                    },
656
                    Place::Projection(ref $($mutability)* proj) => {
657
                        self.visit_projection(proj, context, location);
658
                    }
659 660
                }
            }
661

662 663
            fn super_static(&mut self,
                            static_: & $($mutability)* Static<'tcx>,
664
                            _context: PlaceContext<'tcx>,
665 666 667 668 669 670
                            location: Location) {
                let Static {
                    ref $($mutability)* def_id,
                    ref $($mutability)* ty,
                } = *static_;
                self.visit_def_id(def_id, location);
671
                self.visit_ty(ty, TyContext::Location(location));
672 673
            }

N
Niko Matsakis 已提交
674
            fn super_projection(&mut self,
675 676
                                proj: & $($mutability)* PlaceProjection<'tcx>,
                                context: PlaceContext<'tcx>,
677
                                location: Location) {
N
Niko Matsakis 已提交
678 679 680 681
                let Projection {
                    ref $($mutability)* base,
                    ref $($mutability)* elem,
                } = *proj;
682
                let context = if context.is_mutating_use() {
683
                    PlaceContext::Projection(Mutability::Mut)
684
                } else {
685
                    PlaceContext::Projection(Mutability::Not)
686
                };
687
                self.visit_place(base, context, location);
688
                self.visit_projection_elem(elem, context, location);
N
Niko Matsakis 已提交
689 690 691
            }

            fn super_projection_elem(&mut self,
692 693
                                     proj: & $($mutability)* PlaceElem<'tcx>,
                                     _context: PlaceContext<'tcx>,
694
                                     location: Location) {
N
Niko Matsakis 已提交
695 696 697
                match *proj {
                    ProjectionElem::Deref => {
                    }
698 699
                    ProjectionElem::Subslice { from: _, to: _ } => {
                    }
N
Niko Matsakis 已提交
700
                    ProjectionElem::Field(_field, ref $($mutability)* ty) => {
701
                        self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
702
                    }
703
                    ProjectionElem::Index(ref $($mutability)* local) => {
704
                        self.visit_local(local, PlaceContext::Copy, location);
N
Niko Matsakis 已提交
705 706 707 708 709 710 711 712 713 714
                    }
                    ProjectionElem::ConstantIndex { offset: _,
                                                    min_length: _,
                                                    from_end: _ } => {
                    }
                    ProjectionElem::Downcast(_adt_def, _variant_index) => {
                    }
                }
            }

715
            fn super_local_decl(&mut self,
716
                                local: Local,
717 718
                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
                let LocalDecl {
N
Niko Matsakis 已提交
719 720
                    mutability: _,
                    ref $($mutability)* ty,
721
                    name: _,
722
                    ref $($mutability)* source_info,
723
                    ref $($mutability)* visibility_scope,
724
                    internal: _,
725
                    is_user_variable: _,
726
                } = *local_decl;
N
Niko Matsakis 已提交
727

728 729
                self.visit_ty(ty, TyContext::LocalDecl {
                    local,
730
                    source_info: *source_info,
731
                });
732
                self.visit_source_info(source_info);
733
                self.visit_source_scope(visibility_scope);
N
Niko Matsakis 已提交
734 735
            }

736 737
            fn super_source_scope(&mut self,
                                      _scope: & $($mutability)* SourceScope) {
N
Niko Matsakis 已提交
738 739
            }

740 741 742
            fn super_branch(&mut self,
                            _source: BasicBlock,
                            _target: BasicBlock) {
743 744
            }

745
            fn super_constant(&mut self,
746 747
                              constant: & $($mutability)* Constant<'tcx>,
                              location: Location) {
N
Niko Matsakis 已提交
748 749 750
                let Constant {
                    ref $($mutability)* span,
                    ref $($mutability)* ty,
751
                    ref $($mutability)* user_ty,
N
Niko Matsakis 已提交
752 753 754 755
                    ref $($mutability)* literal,
                } = *constant;

                self.visit_span(span);
756
                self.visit_ty(ty, TyContext::Location(location));
757
                drop(user_ty); // no visit method for this
758
                self.visit_const(literal, location);
759 760
            }

761
            fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
762 763
            }

764
            fn super_span(&mut self, _span: & $($mutability)* Span) {
765
            }
N
Niko Matsakis 已提交
766

767 768 769 770 771 772 773
            fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
                let SourceInfo {
                    ref $($mutability)* span,
                    ref $($mutability)* scope,
                } = *source_info;

                self.visit_span(span);
774
                self.visit_source_scope(scope);
775 776
            }

777 778 779
            fn super_canonical_ty(&mut self, _ty: & $($mutability)* CanonicalTy<'tcx>) {
            }

N
Niko Matsakis 已提交
780 781 782
            fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
            }

783 784 785 786 787 788
            fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
            }

            fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) {
            }

N
Niko Matsakis 已提交
789 790 791
            fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
            }

792 793
            fn super_generator_substs(&mut self,
                                      _substs: & $($mutability)* GeneratorSubsts<'tcx>) {
794 795
            }

N
Niko Matsakis 已提交
796
            fn super_closure_substs(&mut self,
797
                                    _substs: & $($mutability)* ClosureSubsts<'tcx>) {
N
Niko Matsakis 已提交
798 799
            }

800 801 802 803 804 805 806 807 808 809 810 811 812 813
            // Convenience methods

            fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
                let basic_block = & $($mutability)* mir[location.block];
                if basic_block.statements.len() == location.statement_index {
                    if let Some(ref $($mutability)* terminator) = basic_block.terminator {
                        self.visit_terminator(location.block, terminator, location)
                    }
                } else {
                    let statement = & $($mutability)*
                        basic_block.statements[location.statement_index];
                    self.visit_statement(location.block, statement, location)
                }
            }
814 815
        }
    }
816
}
817

818 819
make_mir_visitor!(Visitor,);
make_mir_visitor!(MutVisitor,mut);
820

S
Santiago Pastorino 已提交
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
pub trait MirVisitable<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
    {
        visitor.visit_statement(location.block, self, location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
    {
        visitor.visit_terminator(location.block, self, location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
    {
        visitor.visit_terminator(location.block, self.as_ref().unwrap(), location)
    }
}

846 847
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
848
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
849 850 851 852 853 854 855 856 857
pub enum TyContext {
    LocalDecl {
        /// The index of the local variable we are visiting.
        local: Local,

        /// The source location where this local variable was declared.
        source_info: SourceInfo,
    },

N
Niko Matsakis 已提交
858 859
    /// The return type of the function.
    ReturnTy(SourceInfo),
860

861 862
    YieldTy(SourceInfo),

N
Niko Matsakis 已提交
863 864
    /// A type found at some location.
    Location(Location),
865 866
}

867
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
868
pub enum PlaceContext<'tcx> {
869
    // Appears as LHS of an assignment
870
    Store,
871

872 873 874 875 876
    // Can often be treated as a Store, but needs to be separate because
    // ASM is allowed to read outputs as well, so a Store-AsmOutput sequence
    // cannot be simplified the way a Store-Store can be.
    AsmOutput,

877 878 879
    // Dest of a call
    Call,

880 881
    // Being dropped
    Drop,
882

883 884
    // Being inspected in some way, like loading a len
    Inspect,
885

886
    // Being borrowed
N
Niko Matsakis 已提交
887
    Borrow { region: Region<'tcx>, kind: BorrowKind },
888

889
    // Used as base for another place, e.g. `x` in `x.y`.
890 891
    //
    // The `Mutability` argument specifies whether the projection is being performed in order to
892
    // (potentially) mutate the place. For example, the projection `x.y` is marked as a mutation
893 894 895 896 897 898 899 900 901 902
    // in these cases:
    //
    //     x.y = ...;
    //     f(&mut x.y);
    //
    // But not in these cases:
    //
    //     z = x.y;
    //     f(&x.y);
    Projection(Mutability),
903 904

    // Consumed as part of an operand
905 906
    Copy,
    Move,
907 908 909 910

    // Starting and ending a storage live range
    StorageLive,
    StorageDead,
911 912 913

    // Validation command
    Validate,
914
}
915

916
impl<'tcx> PlaceContext<'tcx> {
917
    /// Returns true if this place context represents a drop.
918 919
    pub fn is_drop(&self) -> bool {
        match *self {
920
            PlaceContext::Drop => true,
921 922 923 924
            _ => false,
        }
    }

925
    /// Returns true if this place context represents a storage live or storage dead marker.
926 927
    pub fn is_storage_marker(&self) -> bool {
        match *self {
928
            PlaceContext::StorageLive | PlaceContext::StorageDead => true,
929 930 931 932
            _ => false,
        }
    }

933
    /// Returns true if this place context represents a storage live marker.
934 935
    pub fn is_storage_live_marker(&self) -> bool {
        match *self {
936
            PlaceContext::StorageLive => true,
937 938 939 940
            _ => false,
        }
    }

941
    /// Returns true if this place context represents a storage dead marker.
942 943
    pub fn is_storage_dead_marker(&self) -> bool {
        match *self {
944
            PlaceContext::StorageDead => true,
945 946 947 948
            _ => false,
        }
    }

949
    /// Returns true if this place context represents a use that potentially changes the value.
950 951
    pub fn is_mutating_use(&self) -> bool {
        match *self {
952
            PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call |
953
            PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } |
954 955
            PlaceContext::Projection(Mutability::Mut) |
            PlaceContext::Drop => true,
956

957 958 959 960 961 962 963
            PlaceContext::Inspect |
            PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
            PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
            PlaceContext::Projection(Mutability::Not) |
            PlaceContext::Copy | PlaceContext::Move |
            PlaceContext::StorageLive | PlaceContext::StorageDead |
            PlaceContext::Validate => false,
964 965 966
        }
    }

967
    /// Returns true if this place context represents a use that does not change the value.
968 969
    pub fn is_nonmutating_use(&self) -> bool {
        match *self {
970 971 972 973
            PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
            PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
            PlaceContext::Projection(Mutability::Not) |
            PlaceContext::Copy | PlaceContext::Move => true,
974 975

            PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store |
976
            PlaceContext::AsmOutput |
977 978 979
            PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) |
            PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead |
            PlaceContext::Validate => false,
980 981 982 983 984 985 986
        }
    }

    pub fn is_use(&self) -> bool {
        self.is_mutating_use() || self.is_nonmutating_use()
    }
}