visit.rs 38.1 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::{ClosureSubsts, Region, Ty, GeneratorInterior};
E
Eduard Burtescu 已提交
14
use mir::*;
15
use rustc_const_math::ConstUsize;
16
use syntax_pos::Span;
N
Niko Matsakis 已提交
17

N
Niko Matsakis 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
// # 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
38
// avoids duplication with other visitors like `TypeFoldable`.
N
Niko Matsakis 已提交
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 79
//
// ## 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.

80 81 82 83 84
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 已提交
85

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

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

96 97 98
            fn visit_visibility_scope_data(&mut self,
                                           scope_data: & $($mutability)* VisibilityScopeData) {
                self.super_visibility_scope_data(scope_data);
N
Niko Matsakis 已提交
99 100
            }

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

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

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

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

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

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

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

148 149
            fn visit_lvalue(&mut self,
                            lvalue: & $($mutability)* Lvalue<'tcx>,
150
                            context: LvalueContext<'tcx>,
151 152
                            location: Location) {
                self.super_lvalue(lvalue, context, location);
N
Niko Matsakis 已提交
153 154
            }

155 156 157 158 159 160 161
            fn visit_static(&mut self,
                            static_: & $($mutability)* Static<'tcx>,
                            context: LvalueContext<'tcx>,
                            location: Location) {
                self.super_static(static_, context, location);
            }

N
Niko Matsakis 已提交
162 163
            fn visit_projection(&mut self,
                                lvalue: & $($mutability)* LvalueProjection<'tcx>,
164
                                context: LvalueContext<'tcx>,
165 166
                                location: Location) {
                self.super_projection(lvalue, context, location);
N
Niko Matsakis 已提交
167 168 169 170
            }

            fn visit_projection_elem(&mut self,
                                     lvalue: & $($mutability)* LvalueElem<'tcx>,
171
                                     context: LvalueContext<'tcx>,
172 173
                                     location: Location) {
                self.super_projection_elem(lvalue, context, location);
N
Niko Matsakis 已提交
174 175
            }

176 177 178 179
            fn visit_branch(&mut self,
                            source: BasicBlock,
                            target: BasicBlock) {
                self.super_branch(source, target);
N
Niko Matsakis 已提交
180 181
            }

182
            fn visit_constant(&mut self,
183 184 185
                              constant: & $($mutability)* Constant<'tcx>,
                              location: Location) {
                self.super_constant(constant, location);
N
Niko Matsakis 已提交
186 187
            }

188
            fn visit_literal(&mut self,
189 190 191
                             literal: & $($mutability)* Literal<'tcx>,
                             location: Location) {
                self.super_literal(literal, 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 220 221 222 223 224 225 226 227
            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 已提交
228
            fn visit_substs(&mut self,
229 230
                            substs: & $($mutability)* &'tcx Substs<'tcx>,
                            _: Location) {
N
Niko Matsakis 已提交
231 232 233 234
                self.super_substs(substs);
            }

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

240 241 242 243 244 245
            fn visit_generator_interior(&mut self,
                                    interior: & $($mutability)* GeneratorInterior<'tcx>,
                                    _: Location) {
                self.super_generator_interior(interior);
            }

246 247 248 249 250 251
            fn visit_const_int(&mut self,
                               const_int: &ConstInt,
                               _: Location) {
                self.super_const_int(const_int);
            }

N
Niko Matsakis 已提交
252
            fn visit_const_usize(&mut self,
253 254
                                 const_usize: & $($mutability)* ConstUsize,
                                 _: Location) {
N
Niko Matsakis 已提交
255 256 257
                self.super_const_usize(const_usize);
            }

258
            fn visit_local_decl(&mut self,
259
                                local: Local,
260
                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
261
                self.super_local_decl(local, local_decl);
N
Niko Matsakis 已提交
262 263
            }

J
John Kåre Alsaker 已提交
264
            fn visit_local(&mut self,
265 266 267
                            _local: & $($mutability)* Local,
                            _context: LvalueContext<'tcx>,
                            _location: Location) {
J
John Kåre Alsaker 已提交
268 269
            }

270 271 272
            fn visit_visibility_scope(&mut self,
                                      scope: & $($mutability)* VisibilityScope) {
                self.super_visibility_scope(scope);
N
Niko Matsakis 已提交
273 274
            }

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

278 279
            fn super_mir(&mut self,
                         mir: & $($mutability)* Mir<'tcx>) {
280 281 282 283 284 285 286 287 288
                // 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);
289
                }
N
Niko Matsakis 已提交
290

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

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

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

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

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

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

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

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

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

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

351
                self.visit_source_info(source_info);
N
Niko Matsakis 已提交
352
                match *kind {
353 354
                    StatementKind::Assign(ref $($mutability)* lvalue,
                                          ref $($mutability)* rvalue) => {
355
                        self.visit_assign(block, lvalue, rvalue, location);
356
                    }
357
                    StatementKind::EndRegion(_) => {}
358
                    StatementKind::Validate(_, ref $($mutability)* lvalues) => {
359 360 361
                        for operand in lvalues {
                            self.visit_lvalue(& $($mutability)* operand.lval,
                                              LvalueContext::Validate, location);
362 363
                            self.visit_ty(& $($mutability)* operand.ty,
                                          TyContext::Location(location));
364 365
                        }
                    }
366
                    StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
367
                        self.visit_lvalue(lvalue, LvalueContext::Store, location);
368
                    }
369 370
                    StatementKind::StorageLive(ref $($mutability)* local) => {
                        self.visit_local(local, LvalueContext::StorageLive, location);
371
                    }
372 373
                    StatementKind::StorageDead(ref $($mutability)* local) => {
                        self.visit_local(local, LvalueContext::StorageDead, location);
374
                    }
375 376 377 378 379 380 381 382 383 384
                    StatementKind::InlineAsm { ref $($mutability)* outputs,
                                               ref $($mutability)* inputs,
                                               asm: _ } => {
                        for output in & $($mutability)* outputs[..] {
                            self.visit_lvalue(output, LvalueContext::Store, location);
                        }
                        for input in & $($mutability)* inputs[..] {
                            self.visit_operand(input, location);
                        }
                    }
385
                    StatementKind::Nop => {}
386
                }
N
Niko Matsakis 已提交
387
            }
388

389 390 391
            fn super_assign(&mut self,
                            _block: BasicBlock,
                            lvalue: &$($mutability)* Lvalue<'tcx>,
392 393 394 395
                            rvalue: &$($mutability)* Rvalue<'tcx>,
                            location: Location) {
                self.visit_lvalue(lvalue, LvalueContext::Store, location);
                self.visit_rvalue(rvalue, location);
396
            }
397

398 399
            fn super_terminator(&mut self,
                                block: BasicBlock,
400 401
                                terminator: &$($mutability)* Terminator<'tcx>,
                                location: Location) {
N
Niko Matsakis 已提交
402
                let Terminator {
403
                    ref $($mutability)* source_info,
N
Niko Matsakis 已提交
404 405 406
                    ref $($mutability)* kind,
                } = *terminator;

407
                self.visit_source_info(source_info);
408
                self.visit_terminator_kind(block, kind, location);
N
Niko Matsakis 已提交
409 410 411 412
            }

            fn super_terminator_kind(&mut self,
                                     block: BasicBlock,
413 414
                                     kind: & $($mutability)* TerminatorKind<'tcx>,
                                     source_location: Location) {
N
Niko Matsakis 已提交
415
                match *kind {
416
                    TerminatorKind::Goto { target } => {
417 418
                        self.visit_branch(block, target);
                    }
419

420
                    TerminatorKind::SwitchInt { ref $($mutability)* discr,
N
Niko Matsakis 已提交
421
                                                ref $($mutability)* switch_ty,
422
                                                ref values,
423
                                                ref targets } => {
424
                        self.visit_operand(discr, source_location);
425
                        self.visit_ty(switch_ty, TyContext::Location(source_location));
426 427
                        for value in &values[..] {
                            self.visit_const_int(value, source_location);
N
Niko Matsakis 已提交
428
                        }
429 430 431 432
                        for &target in targets {
                            self.visit_branch(block, target);
                        }
                    }
433

434
                    TerminatorKind::Resume |
A
Alex Crichton 已提交
435
                    TerminatorKind::Return |
J
John Kåre Alsaker 已提交
436
                    TerminatorKind::GeneratorDrop |
437
                    TerminatorKind::Unreachable => {
438
                    }
439

440
                    TerminatorKind::Drop { ref $($mutability)* location,
441 442
                                           target,
                                           unwind } => {
443
                        self.visit_lvalue(location, LvalueContext::Drop, source_location);
444 445 446 447 448 449 450 451
                        self.visit_branch(block, target);
                        unwind.map(|t| self.visit_branch(block, t));
                    }

                    TerminatorKind::DropAndReplace { ref $($mutability)* location,
                                                     ref $($mutability)* value,
                                                     target,
                                                     unwind } => {
452 453
                        self.visit_lvalue(location, LvalueContext::Drop, source_location);
                        self.visit_operand(value, source_location);
454 455 456 457
                        self.visit_branch(block, target);
                        unwind.map(|t| self.visit_branch(block, t));
                    }

458 459 460 461
                    TerminatorKind::Call { ref $($mutability)* func,
                                           ref $($mutability)* args,
                                           ref $($mutability)* destination,
                                           cleanup } => {
462
                        self.visit_operand(func, source_location);
463
                        for arg in args {
464
                            self.visit_operand(arg, source_location);
465
                        }
S
Simonas Kazlauskas 已提交
466
                        if let Some((ref $($mutability)* destination, target)) = *destination {
467
                            self.visit_lvalue(destination, LvalueContext::Call, source_location);
468 469
                            self.visit_branch(block, target);
                        }
S
Simonas Kazlauskas 已提交
470
                        cleanup.map(|t| self.visit_branch(block, t));
471
                    }
472 473 474 475 476 477

                    TerminatorKind::Assert { ref $($mutability)* cond,
                                             expected: _,
                                             ref $($mutability)* msg,
                                             target,
                                             cleanup } => {
478 479
                        self.visit_operand(cond, source_location);
                        self.visit_assert_message(msg, source_location);
480 481 482
                        self.visit_branch(block, target);
                        cleanup.map(|t| self.visit_branch(block, t));
                    }
J
John Kåre Alsaker 已提交
483

J
John Kåre Alsaker 已提交
484
                    TerminatorKind::Yield { ref $($mutability)* value,
J
John Kåre Alsaker 已提交
485 486 487 488 489
                                              resume,
                                              drop } => {
                        self.visit_operand(value, source_location);
                        self.visit_branch(block, resume);
                        drop.map(|t| self.visit_branch(block, t));
490

J
John Kåre Alsaker 已提交
491 492
                    }

493 494 495 496 497 498
                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
                        self.visit_branch(block, real_target);
                        for target in imaginary_targets {
                            self.visit_branch(block, *target);
                        }
                    }
499 500 501 502
                }
            }

            fn super_assert_message(&mut self,
503 504
                                    msg: & $($mutability)* AssertMessage<'tcx>,
                                    location: Location) {
505 506 507 508 509
                match *msg {
                    AssertMessage::BoundsCheck {
                        ref $($mutability)* len,
                        ref $($mutability)* index
                    } => {
510 511
                        self.visit_operand(len, location);
                        self.visit_operand(index, location);
512
                    }
J
John Kåre Alsaker 已提交
513 514 515
                    AssertMessage::Math(_) => {},
                    AssertMessage::GeneratorResumedAfterReturn => {},
                    AssertMessage::GeneratorResumedAfterPanic => {},
516 517
                }
            }
518

519
            fn super_rvalue(&mut self,
520 521
                            rvalue: & $($mutability)* Rvalue<'tcx>,
                            location: Location) {
522 523
                match *rvalue {
                    Rvalue::Use(ref $($mutability)* operand) => {
524
                        self.visit_operand(operand, location);
525
                    }
526

527
                    Rvalue::Repeat(ref $($mutability)* value,
S
Simonas Kazlauskas 已提交
528
                                   ref $($mutability)* length) => {
529
                        self.visit_operand(value, location);
S
Simonas Kazlauskas 已提交
530
                        self.visit_const_usize(length, location);
531
                    }
532

533 534
                    Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
                        self.visit_region(r, location);
535
                        self.visit_lvalue(path, LvalueContext::Borrow {
536
                            region: *r,
537
                            kind: bk
538
                        }, location);
539
                    }
540

541
                    Rvalue::Len(ref $($mutability)* path) => {
542
                        self.visit_lvalue(path, LvalueContext::Inspect, location);
543
                    }
544

N
Niko Matsakis 已提交
545 546 547
                    Rvalue::Cast(_cast_kind,
                                 ref $($mutability)* operand,
                                 ref $($mutability)* ty) => {
548
                        self.visit_operand(operand, location);
549
                        self.visit_ty(ty, TyContext::Location(location));
550
                    }
551

N
Niko Matsakis 已提交
552
                    Rvalue::BinaryOp(_bin_op,
J
James Miller 已提交
553 554 555
                                     ref $($mutability)* lhs,
                                     ref $($mutability)* rhs) |
                    Rvalue::CheckedBinaryOp(_bin_op,
556 557
                                     ref $($mutability)* lhs,
                                     ref $($mutability)* rhs) => {
558 559
                        self.visit_operand(lhs, location);
                        self.visit_operand(rhs, location);
560
                    }
561

N
Niko Matsakis 已提交
562
                    Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
563
                        self.visit_operand(op, location);
564
                    }
565

566 567 568 569
                    Rvalue::Discriminant(ref $($mutability)* lvalue) => {
                        self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
                    }

570
                    Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
571
                        self.visit_ty(ty, TyContext::Location(location));
572
                    }
573

574 575
                    Rvalue::Aggregate(ref $($mutability)* kind,
                                      ref $($mutability)* operands) => {
A
Ariel Ben-Yehuda 已提交
576
                        let kind = &$($mutability)* **kind;
577
                        match *kind {
S
Simonas Kazlauskas 已提交
578
                            AggregateKind::Array(ref $($mutability)* ty) => {
579
                                self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
580 581 582 583 584
                            }
                            AggregateKind::Tuple => {
                            }
                            AggregateKind::Adt(_adt_def,
                                               _variant_index,
585 586
                                               ref $($mutability)* substs,
                                               _active_field_index) => {
587
                                self.visit_substs(substs, location);
N
Niko Matsakis 已提交
588 589 590
                            }
                            AggregateKind::Closure(ref $($mutability)* def_id,
                                                   ref $($mutability)* closure_substs) => {
591
                                self.visit_def_id(def_id, location);
592
                                self.visit_closure_substs(closure_substs, location);
593
                            }
J
John Kåre Alsaker 已提交
594
                            AggregateKind::Generator(ref $($mutability)* def_id,
595 596
                                                   ref $($mutability)* closure_substs,
                                                   ref $($mutability)* interior) => {
J
John Kåre Alsaker 已提交
597
                                self.visit_def_id(def_id, location);
598
                                self.visit_closure_substs(closure_substs, location);
599
                                self.visit_generator_interior(interior, location);
J
John Kåre Alsaker 已提交
600
                            }
601 602
                        }

N
Niko Matsakis 已提交
603
                        for operand in operands {
604
                            self.visit_operand(operand, location);
605 606
                        }
                    }
607 608 609
                }
            }

610
            fn super_operand(&mut self,
611 612
                             operand: & $($mutability)* Operand<'tcx>,
                             location: Location) {
613 614
                match *operand {
                    Operand::Consume(ref $($mutability)* lvalue) => {
615
                        self.visit_lvalue(lvalue, LvalueContext::Consume, location);
616 617
                    }
                    Operand::Constant(ref $($mutability)* constant) => {
618
                        self.visit_constant(constant, location);
619
                    }
620 621 622
                }
            }

623 624
            fn super_lvalue(&mut self,
                            lvalue: & $($mutability)* Lvalue<'tcx>,
625
                            context: LvalueContext<'tcx>,
626
                            location: Location) {
627
                match *lvalue {
J
John Kåre Alsaker 已提交
628
                    Lvalue::Local(ref $($mutability)* local) => {
629
                        self.visit_local(local, context, location);
630
                    }
631 632
                    Lvalue::Static(ref $($mutability)* static_) => {
                        self.visit_static(static_, context, location);
633 634
                    }
                    Lvalue::Projection(ref $($mutability)* proj) => {
635
                        self.visit_projection(proj, context, location);
636
                    }
637 638
                }
            }
639

640 641 642 643 644 645 646 647 648
            fn super_static(&mut self,
                            static_: & $($mutability)* Static<'tcx>,
                            _context: LvalueContext<'tcx>,
                            location: Location) {
                let Static {
                    ref $($mutability)* def_id,
                    ref $($mutability)* ty,
                } = *static_;
                self.visit_def_id(def_id, location);
649
                self.visit_ty(ty, TyContext::Location(location));
650 651
            }

N
Niko Matsakis 已提交
652 653
            fn super_projection(&mut self,
                                proj: & $($mutability)* LvalueProjection<'tcx>,
654
                                context: LvalueContext<'tcx>,
655
                                location: Location) {
N
Niko Matsakis 已提交
656 657 658 659
                let Projection {
                    ref $($mutability)* base,
                    ref $($mutability)* elem,
                } = *proj;
660 661 662 663 664 665
                let context = if context.is_mutating_use() {
                    LvalueContext::Projection(Mutability::Mut)
                } else {
                    LvalueContext::Projection(Mutability::Not)
                };
                self.visit_lvalue(base, context, location);
666
                self.visit_projection_elem(elem, context, location);
N
Niko Matsakis 已提交
667 668 669 670
            }

            fn super_projection_elem(&mut self,
                                     proj: & $($mutability)* LvalueElem<'tcx>,
671
                                     _context: LvalueContext<'tcx>,
672
                                     location: Location) {
N
Niko Matsakis 已提交
673 674 675
                match *proj {
                    ProjectionElem::Deref => {
                    }
676 677
                    ProjectionElem::Subslice { from: _, to: _ } => {
                    }
N
Niko Matsakis 已提交
678
                    ProjectionElem::Field(_field, ref $($mutability)* ty) => {
679
                        self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
680
                    }
681 682
                    ProjectionElem::Index(ref $($mutability)* local) => {
                        self.visit_local(local, LvalueContext::Consume, location);
N
Niko Matsakis 已提交
683 684 685 686 687 688 689 690 691 692
                    }
                    ProjectionElem::ConstantIndex { offset: _,
                                                    min_length: _,
                                                    from_end: _ } => {
                    }
                    ProjectionElem::Downcast(_adt_def, _variant_index) => {
                    }
                }
            }

693
            fn super_local_decl(&mut self,
694
                                local: Local,
695 696
                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
                let LocalDecl {
N
Niko Matsakis 已提交
697 698
                    mutability: _,
                    ref $($mutability)* ty,
699
                    name: _,
700
                    ref $($mutability)* source_info,
701
                    internal: _,
702
                    ref $($mutability)* lexical_scope,
703
                    is_user_variable: _,
704
                } = *local_decl;
N
Niko Matsakis 已提交
705

706 707 708 709
                self.visit_ty(ty, TyContext::LocalDecl {
                    local,
                    source_info: *source_info,
                });
710
                self.visit_source_info(source_info);
711
                self.visit_visibility_scope(lexical_scope);
N
Niko Matsakis 已提交
712 713
            }

714 715
            fn super_visibility_scope(&mut self,
                                      _scope: & $($mutability)* VisibilityScope) {
N
Niko Matsakis 已提交
716 717
            }

718 719 720
            fn super_branch(&mut self,
                            _source: BasicBlock,
                            _target: BasicBlock) {
721 722
            }

723
            fn super_constant(&mut self,
724 725
                              constant: & $($mutability)* Constant<'tcx>,
                              location: Location) {
N
Niko Matsakis 已提交
726 727 728 729 730 731 732
                let Constant {
                    ref $($mutability)* span,
                    ref $($mutability)* ty,
                    ref $($mutability)* literal,
                } = *constant;

                self.visit_span(span);
733
                self.visit_ty(ty, TyContext::Location(location));
734
                self.visit_literal(literal, location);
735 736
            }

737
            fn super_literal(&mut self,
738 739
                             literal: & $($mutability)* Literal<'tcx>,
                             location: Location) {
740
                match *literal {
N
Niko Matsakis 已提交
741
                    Literal::Value { ref $($mutability)* value } => {
742
                        self.visit_const(value, location);
743
                    }
744
                    Literal::Promoted { index: _ } => {}
745 746 747
                }
            }

748
            fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
749 750
            }

751
            fn super_span(&mut self, _span: & $($mutability)* Span) {
752
            }
N
Niko Matsakis 已提交
753

754 755 756 757 758 759 760 761 762 763
            fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
                let SourceInfo {
                    ref $($mutability)* span,
                    ref $($mutability)* scope,
                } = *source_info;

                self.visit_span(span);
                self.visit_visibility_scope(scope);
            }

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

767 768 769 770 771 772
            fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
            }

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

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

776 777 778 779
            fn super_generator_interior(&mut self,
                                    _interior: & $($mutability)* GeneratorInterior<'tcx>) {
            }

N
Niko Matsakis 已提交
780
            fn super_closure_substs(&mut self,
781
                                    _substs: & $($mutability)* ClosureSubsts<'tcx>) {
N
Niko Matsakis 已提交
782 783
            }

784
            fn super_const_int(&mut self, _const_int: &ConstInt) {
N
Niko Matsakis 已提交
785 786
            }

787
            fn super_const_usize(&mut self, _const_usize: & $($mutability)* ConstUsize) {
N
Niko Matsakis 已提交
788
            }
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803

            // 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)
                }
            }
804 805
        }
    }
806
}
807

808 809
make_mir_visitor!(Visitor,);
make_mir_visitor!(MutVisitor,mut);
810

811 812
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
813
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
814 815 816 817 818 819 820 821 822
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 已提交
823 824
    /// The return type of the function.
    ReturnTy(SourceInfo),
825

N
Niko Matsakis 已提交
826 827
    /// A type found at some location.
    Location(Location),
828 829
}

830
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
831
pub enum LvalueContext<'tcx> {
832
    // Appears as LHS of an assignment
833
    Store,
834

835 836 837
    // Dest of a call
    Call,

838 839
    // Being dropped
    Drop,
840

841 842
    // Being inspected in some way, like loading a len
    Inspect,
843

844
    // Being borrowed
N
Niko Matsakis 已提交
845
    Borrow { region: Region<'tcx>, kind: BorrowKind },
846

847 848 849 850 851 852 853 854 855 856 857 858 859 860
    // Used as base for another lvalue, e.g. `x` in `x.y`.
    //
    // The `Mutability` argument specifies whether the projection is being performed in order to
    // (potentially) mutate the lvalue. For example, the projection `x.y` is marked as a mutation
    // in these cases:
    //
    //     x.y = ...;
    //     f(&mut x.y);
    //
    // But not in these cases:
    //
    //     z = x.y;
    //     f(&x.y);
    Projection(Mutability),
861 862 863

    // Consumed as part of an operand
    Consume,
864 865 866 867

    // Starting and ending a storage live range
    StorageLive,
    StorageDead,
868 869 870

    // Validation command
    Validate,
871
}
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916

impl<'tcx> LvalueContext<'tcx> {
    /// Returns true if this lvalue context represents a drop.
    pub fn is_drop(&self) -> bool {
        match *self {
            LvalueContext::Drop => true,
            _ => false,
        }
    }

    /// Returns true if this lvalue context represents a storage live or storage dead marker.
    pub fn is_storage_marker(&self) -> bool {
        match *self {
            LvalueContext::StorageLive | LvalueContext::StorageDead => true,
            _ => false,
        }
    }

    /// Returns true if this lvalue context represents a storage live marker.
    pub fn is_storage_live_marker(&self) -> bool {
        match *self {
            LvalueContext::StorageLive => true,
            _ => false,
        }
    }

    /// Returns true if this lvalue context represents a storage dead marker.
    pub fn is_storage_dead_marker(&self) -> bool {
        match *self {
            LvalueContext::StorageDead => true,
            _ => false,
        }
    }

    /// Returns true if this lvalue context represents a use that potentially changes the value.
    pub fn is_mutating_use(&self) -> bool {
        match *self {
            LvalueContext::Store | LvalueContext::Call |
            LvalueContext::Borrow { kind: BorrowKind::Mut, .. } |
            LvalueContext::Projection(Mutability::Mut) |
            LvalueContext::Drop => true,
            LvalueContext::Inspect |
            LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
            LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
            LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume |
917 918
            LvalueContext::StorageLive | LvalueContext::StorageDead |
            LvalueContext::Validate => false,
919 920 921 922 923 924 925 926 927 928 929
        }
    }

    /// Returns true if this lvalue context represents a use that does not change the value.
    pub fn is_nonmutating_use(&self) -> bool {
        match *self {
            LvalueContext::Inspect | LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
            LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
            LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume => true,
            LvalueContext::Borrow { kind: BorrowKind::Mut, .. } | LvalueContext::Store |
            LvalueContext::Call | LvalueContext::Projection(Mutability::Mut) |
930 931
            LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead |
            LvalueContext::Validate => false,
932 933 934 935 936 937 938
        }
    }

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