visit.rs 45.4 KB
Newer Older
M
Mark Rousskov 已提交
1
use crate::mir::*;
C
csmoe 已提交
2
use crate::ty::subst::SubstsRef;
C
csmoe 已提交
3
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
4
use rustc_span::Span;
N
Niko Matsakis 已提交
5

N
Niko Matsakis 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// # 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
25
// MIR, e.g., types, spans, etc, but simply visit them and stop. This
26
// avoids duplication with other visitors like `TypeFoldable`.
N
Niko Matsakis 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39
//
// ## 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,
M
Matthew Jasper 已提交
40
//                           data: & $($mutability)? BasicBlockData<'tcx>) {
N
Niko Matsakis 已提交
41
//     let BasicBlockData {
M
Matthew Jasper 已提交
42 43
//         statements,
//         terminator,
N
Niko Matsakis 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
//         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.

68
macro_rules! make_mir_visitor {
M
Matthew Jasper 已提交
69
    ($visitor_trait_name:ident, $($mutability:ident)?) => {
70 71 72
        pub trait $visitor_trait_name<'tcx> {
            // Override these, and call `self.super_xxx` to revert back to the
            // default behavior.
N
Niko Matsakis 已提交
73

74 75
            fn visit_body(
                &mut self,
D
Dylan MacKenzie 已提交
76
                body: &$($mutability)? Body<'tcx>,
77
            ) {
78
                self.super_body(body);
N
Niko Matsakis 已提交
79 80
            }

81 82
            fn visit_basic_block_data(&mut self,
                                      block: BasicBlock,
M
Matthew Jasper 已提交
83
                                      data: & $($mutability)? BasicBlockData<'tcx>) {
84
                self.super_basic_block_data(block, data);
N
Niko Matsakis 已提交
85 86
            }

87
            fn visit_source_scope_data(&mut self,
M
Matthew Jasper 已提交
88
                                           scope_data: & $($mutability)? SourceScopeData) {
89
                self.super_source_scope_data(scope_data);
N
Niko Matsakis 已提交
90 91
            }

92
            fn visit_statement(&mut self,
M
Matthew Jasper 已提交
93
                               statement: & $($mutability)? Statement<'tcx>,
94
                               location: Location) {
95
                self.super_statement(statement, location);
N
Niko Matsakis 已提交
96 97
            }

98
            fn visit_assign(&mut self,
M
Matthew Jasper 已提交
99 100
                            place: & $($mutability)? Place<'tcx>,
                            rvalue: & $($mutability)? Rvalue<'tcx>,
101
                            location: Location) {
102
                self.super_assign(place, rvalue, location);
N
Niko Matsakis 已提交
103 104
            }

105
            fn visit_terminator(&mut self,
M
Matthew Jasper 已提交
106
                                terminator: & $($mutability)? Terminator<'tcx>,
107
                                location: Location) {
108
                self.super_terminator(terminator, location);
109 110
            }

N
Niko Matsakis 已提交
111
            fn visit_terminator_kind(&mut self,
M
Matthew Jasper 已提交
112
                                     kind: & $($mutability)? TerminatorKind<'tcx>,
113
                                     location: Location) {
114
                self.super_terminator_kind(kind, location);
N
Niko Matsakis 已提交
115 116
            }

117
            fn visit_assert_message(&mut self,
M
Matthew Jasper 已提交
118
                                    msg: & $($mutability)? AssertMessage<'tcx>,
119 120
                                    location: Location) {
                self.super_assert_message(msg, location);
121 122
            }

123
            fn visit_rvalue(&mut self,
M
Matthew Jasper 已提交
124
                            rvalue: & $($mutability)? Rvalue<'tcx>,
125 126
                            location: Location) {
                self.super_rvalue(rvalue, location);
N
Niko Matsakis 已提交
127 128
            }

129
            fn visit_operand(&mut self,
M
Matthew Jasper 已提交
130
                             operand: & $($mutability)? Operand<'tcx>,
131 132
                             location: Location) {
                self.super_operand(operand, location);
133
            }
N
Niko Matsakis 已提交
134

135
            fn visit_ascribe_user_ty(&mut self,
M
Matthew Jasper 已提交
136 137
                                     place: & $($mutability)? Place<'tcx>,
                                     variance: & $($mutability)? ty::Variance,
138
                                     user_ty: & $($mutability)? UserTypeProjection,
139
                                     location: Location) {
140
                self.super_ascribe_user_ty(place, variance, user_ty, location);
D
David Wood 已提交
141 142
            }

143
            fn visit_retag(&mut self,
M
Matthew Jasper 已提交
144 145
                           kind: & $($mutability)? RetagKind,
                           place: & $($mutability)? Place<'tcx>,
146
                           location: Location) {
147
                self.super_retag(kind, place, location);
148 149
            }

150
            fn visit_place(&mut self,
M
Matthew Jasper 已提交
151
                            place: & $($mutability)? Place<'tcx>,
152
                            context: PlaceContext,
153
                            location: Location) {
154
                self.super_place(place, context, location);
N
Niko Matsakis 已提交
155 156
            }

157
            visit_place_fns!($($mutability)?);
158

159
            fn visit_constant(&mut self,
M
Matthew Jasper 已提交
160
                              constant: & $($mutability)? Constant<'tcx>,
161 162
                              location: Location) {
                self.super_constant(constant, location);
N
Niko Matsakis 已提交
163 164
            }

165
            fn visit_span(&mut self,
M
Matthew Jasper 已提交
166
                          span: & $($mutability)? Span) {
167
                self.super_span(span);
N
Niko Matsakis 已提交
168 169
            }

170
            fn visit_source_info(&mut self,
M
Matthew Jasper 已提交
171
                                 source_info: & $($mutability)? SourceInfo) {
172 173 174
                self.super_source_info(source_info);
            }

N
Niko Matsakis 已提交
175
            fn visit_ty(&mut self,
F
flip1995 已提交
176
                        ty: $(& $mutability)? Ty<'tcx>,
177
                        _: TyContext) {
N
Niko Matsakis 已提交
178 179 180
                self.super_ty(ty);
            }

181 182
            fn visit_user_type_projection(
                &mut self,
183
                ty: & $($mutability)? UserTypeProjection,
184 185 186 187
            ) {
                self.super_user_type_projection(ty);
            }

N
Niko Matsakis 已提交
188 189
            fn visit_user_type_annotation(
                &mut self,
D
David Wood 已提交
190
                index: UserTypeAnnotationIndex,
M
Matthew Jasper 已提交
191
                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
N
Niko Matsakis 已提交
192
            ) {
D
David Wood 已提交
193
                self.super_user_type_annotation(index, ty);
194 195
            }

196
            fn visit_region(&mut self,
M
Matthew Jasper 已提交
197
                            region: & $($mutability)? ty::Region<'tcx>,
198 199 200 201 202
                            _: Location) {
                self.super_region(region);
            }

            fn visit_const(&mut self,
O
Oliver Scherer 已提交
203
                           constant: & $($mutability)? &'tcx ty::Const<'tcx>,
204 205 206 207
                           _: Location) {
                self.super_const(constant);
            }

N
Niko Matsakis 已提交
208
            fn visit_substs(&mut self,
C
csmoe 已提交
209
                            substs: & $($mutability)? SubstsRef<'tcx>,
210
                            _: Location) {
N
Niko Matsakis 已提交
211 212 213
                self.super_substs(substs);
            }

214
            fn visit_local_decl(&mut self,
215
                                local: Local,
M
Matthew Jasper 已提交
216
                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
217
                self.super_local_decl(local, local_decl);
N
Niko Matsakis 已提交
218 219
            }

220 221 222 223 224
            fn visit_var_debug_info(&mut self,
                                    var_debug_info: & $($mutability)* VarDebugInfo<'tcx>) {
                self.super_var_debug_info(var_debug_info);
            }

J
John Kåre Alsaker 已提交
225
            fn visit_local(&mut self,
M
Matthew Jasper 已提交
226
                            _local: & $($mutability)? Local,
227
                            _context: PlaceContext,
228
                            _location: Location) {
J
John Kåre Alsaker 已提交
229 230
            }

231
            fn visit_source_scope(&mut self,
M
Matthew Jasper 已提交
232
                                      scope: & $($mutability)? SourceScope) {
233
                self.super_source_scope(scope);
N
Niko Matsakis 已提交
234 235
            }

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

239 240
            fn super_body(
                &mut self,
D
Dylan MacKenzie 已提交
241
                body: &$($mutability)? Body<'tcx>,
242
            ) {
243 244
                let span = body.span;
                if let Some(yield_ty) = &$($mutability)? body.yield_ty {
245 246 247 248
                    self.visit_ty(
                        yield_ty,
                        TyContext::YieldTy(SourceInfo::outermost(span))
                    );
249 250
                }

251
                // for best performance, we want to use an iterator rather
252
                // than a for-loop, to avoid calling `body::Body::invalidate` for
253 254
                // each basic block.
                macro_rules! basic_blocks {
255 256
                    (mut) => (body.basic_blocks_mut().iter_enumerated_mut());
                    () => (body.basic_blocks().iter_enumerated());
257
                };
M
Matthew Jasper 已提交
258
                for (bb, data) in basic_blocks!($($mutability)?) {
259
                    self.visit_basic_block_data(bb, data);
260
                }
N
Niko Matsakis 已提交
261

262
                for scope in &$($mutability)? body.source_scopes {
263
                    self.visit_source_scope_data(scope);
N
Niko Matsakis 已提交
264 265
                }

266 267 268 269
                self.visit_ty(
                    &$($mutability)? body.return_ty(),
                    TyContext::ReturnTy(SourceInfo::outermost(body.span))
                );
N
Niko Matsakis 已提交
270

271 272
                for local in body.local_decls.indices() {
                    self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
N
Niko Matsakis 已提交
273 274
                }

275
                macro_rules! type_annotations {
276 277
                    (mut) => (body.user_type_annotations.iter_enumerated_mut());
                    () => (body.user_type_annotations.iter_enumerated());
278 279
                };

M
Matthew Jasper 已提交
280
                for (index, annotation) in type_annotations!($($mutability)?) {
D
David Wood 已提交
281 282 283 284 285
                    self.visit_user_type_annotation(
                        index, annotation
                    );
                }

286 287 288 289
                for var_debug_info in &$($mutability)? body.var_debug_info {
                    self.visit_var_debug_info(var_debug_info);
                }

290
                self.visit_span(&$($mutability)? body.span);
291

292
                for const_ in &$($mutability)? body.required_consts {
293 294 295
                    let location = START_BLOCK.start_location();
                    self.visit_constant(const_, location);
                }
N
Niko Matsakis 已提交
296 297
            }

298 299
            fn super_basic_block_data(&mut self,
                                      block: BasicBlock,
M
Matthew Jasper 已提交
300
                                      data: & $($mutability)? BasicBlockData<'tcx>) {
N
Niko Matsakis 已提交
301
                let BasicBlockData {
M
Matthew Jasper 已提交
302 303
                    statements,
                    terminator,
N
Niko Matsakis 已提交
304
                    is_cleanup: _
M
Matthew Jasper 已提交
305
                } = data;
N
Niko Matsakis 已提交
306

307
                let mut index = 0;
N
Niko Matsakis 已提交
308
                for statement in statements {
309
                    let location = Location { block: block, statement_index: index };
310
                    self.visit_statement(statement, location);
311
                    index += 1;
N
Niko Matsakis 已提交
312 313
                }

M
Matthew Jasper 已提交
314
                if let Some(terminator) = terminator {
315
                    let location = Location { block: block, statement_index: index };
316
                    self.visit_terminator(terminator, location);
317
                }
N
Niko Matsakis 已提交
318 319
            }

M
Matthew Jasper 已提交
320
            fn super_source_scope_data(&mut self, scope_data: & $($mutability)? SourceScopeData) {
321
                let SourceScopeData {
M
Matthew Jasper 已提交
322 323
                    span,
                    parent_scope,
324
                    local_data: _,
M
Matthew Jasper 已提交
325
                } = scope_data;
N
Niko Matsakis 已提交
326

327
                self.visit_span(span);
M
Matthew Jasper 已提交
328
                if let Some(parent_scope) = parent_scope {
329
                    self.visit_source_scope(parent_scope);
N
Niko Matsakis 已提交
330 331 332
                }
            }

333
            fn super_statement(&mut self,
M
Matthew Jasper 已提交
334
                               statement: & $($mutability)? Statement<'tcx>,
335
                               location: Location) {
N
Niko Matsakis 已提交
336
                let Statement {
M
Matthew Jasper 已提交
337 338 339
                    source_info,
                    kind,
                } = statement;
N
Niko Matsakis 已提交
340

341
                self.visit_source_info(source_info);
M
Matthew Jasper 已提交
342
                match kind {
343 344 345
                    StatementKind::Assign(
                        box(ref $($mutability)? place, ref $($mutability)? rvalue)
                    ) => {
346
                        self.visit_assign(place, rvalue, location);
347
                    }
M
Matthew Jasper 已提交
348
                    StatementKind::FakeRead(_, place) => {
349 350 351 352 353
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
354
                    }
M
Matthew Jasper 已提交
355
                    StatementKind::SetDiscriminant { place, .. } => {
356 357 358 359 360
                        self.visit_place(
                            place,
                            PlaceContext::MutatingUse(MutatingUseContext::Store),
                            location
                        );
361
                    }
M
Matthew Jasper 已提交
362
                    StatementKind::StorageLive(local) => {
363 364 365 366 367
                        self.visit_local(
                            local,
                            PlaceContext::NonUse(NonUseContext::StorageLive),
                            location
                        );
368
                    }
M
Matthew Jasper 已提交
369
                    StatementKind::StorageDead(local) => {
370 371 372 373 374
                        self.visit_local(
                            local,
                            PlaceContext::NonUse(NonUseContext::StorageDead),
                            location
                        );
375
                    }
A
Amanieu d'Antras 已提交
376
                    StatementKind::LlvmInlineAsm(asm) => {
N
Nicholas Nethercote 已提交
377
                        for output in & $($mutability)? asm.outputs[..] {
378 379 380 381 382
                            self.visit_place(
                                output,
                                PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                location
                            );
383
                        }
N
Nicholas Nethercote 已提交
384
                        for (span, input) in & $($mutability)? asm.inputs[..] {
L
Levente Kurusa 已提交
385
                            self.visit_span(span);
386 387 388
                            self.visit_operand(input, location);
                        }
                    }
M
Matthew Jasper 已提交
389
                    StatementKind::Retag(kind, place) => {
390
                        self.visit_retag(kind, place, location);
391
                    }
392 393 394 395
                    StatementKind::AscribeUserType(
                        box(ref $($mutability)? place, ref $($mutability)? user_ty),
                        variance
                    ) => {
396
                        self.visit_ascribe_user_ty(place, variance, user_ty, location);
D
David Wood 已提交
397
                    }
398
                    StatementKind::Nop => {}
399
                }
N
Niko Matsakis 已提交
400
            }
401

402
            fn super_assign(&mut self,
M
Matthew Jasper 已提交
403 404
                            place: &$($mutability)? Place<'tcx>,
                            rvalue: &$($mutability)? Rvalue<'tcx>,
405
                            location: Location) {
406 407 408 409 410
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Store),
                    location
                );
411
                self.visit_rvalue(rvalue, location);
412
            }
413

414
            fn super_terminator(&mut self,
M
Matthew Jasper 已提交
415
                                terminator: &$($mutability)? Terminator<'tcx>,
416
                                location: Location) {
M
Matthew Jasper 已提交
417
                let Terminator { source_info, kind } = terminator;
N
Niko Matsakis 已提交
418

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

            fn super_terminator_kind(&mut self,
M
Matthew Jasper 已提交
424
                                     kind: & $($mutability)? TerminatorKind<'tcx>,
425
                                     source_location: Location) {
M
Matthew Jasper 已提交
426
                match kind {
427 428 429 430 431 432 433
                    TerminatorKind::Goto { .. } |
                    TerminatorKind::Resume |
                    TerminatorKind::Abort |
                    TerminatorKind::GeneratorDrop |
                    TerminatorKind::Unreachable |
                    TerminatorKind::FalseEdges { .. } |
                    TerminatorKind::FalseUnwind { .. } => {
434
                    }
435

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
                    TerminatorKind::Return => {
                        // `return` logically moves from the return place `_0`. Note that the place
                        // cannot be changed by any visitor, though.
                        let $($mutability)? local = RETURN_PLACE;
                        self.visit_local(
                            & $($mutability)? local,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                            source_location,
                        );

                        assert_eq!(
                            local,
                            RETURN_PLACE,
                            "`MutVisitor` tried to mutate return place of `return` terminator"
                        );
                    }

M
Matthew Jasper 已提交
453 454 455 456
                    TerminatorKind::SwitchInt {
                        discr,
                        switch_ty,
                        values: _,
457
                        targets: _
M
Matthew Jasper 已提交
458
                    } => {
459
                        self.visit_operand(discr, source_location);
460
                        self.visit_ty(switch_ty, TyContext::Location(source_location));
461
                    }
462

M
Matthew Jasper 已提交
463 464
                    TerminatorKind::Drop {
                        location,
465 466
                        target: _,
                        unwind: _,
M
Matthew Jasper 已提交
467
                    } => {
468 469 470 471 472
                        self.visit_place(
                            location,
                            PlaceContext::MutatingUse(MutatingUseContext::Drop),
                            source_location
                        );
473 474
                    }

M
Matthew Jasper 已提交
475 476 477
                    TerminatorKind::DropAndReplace {
                        location,
                        value,
478 479
                        target: _,
                        unwind: _,
M
Matthew Jasper 已提交
480
                    } => {
481 482 483 484 485
                        self.visit_place(
                            location,
                            PlaceContext::MutatingUse(MutatingUseContext::Drop),
                            source_location
                        );
486
                        self.visit_operand(value, source_location);
487 488
                    }

M
Matthew Jasper 已提交
489 490 491 492
                    TerminatorKind::Call {
                        func,
                        args,
                        destination,
493
                        cleanup: _,
M
Matthew Jasper 已提交
494 495
                        from_hir_call: _,
                    } => {
496
                        self.visit_operand(func, source_location);
497
                        for arg in args {
498
                            self.visit_operand(arg, source_location);
499
                        }
500
                        if let Some((destination, _)) = destination {
501 502 503 504 505
                            self.visit_place(
                                destination,
                                PlaceContext::MutatingUse(MutatingUseContext::Call),
                                source_location
                            );
506 507
                        }
                    }
508

M
Matthew Jasper 已提交
509 510 511 512
                    TerminatorKind::Assert {
                        cond,
                        expected: _,
                        msg,
513 514
                        target: _,
                        cleanup: _,
M
Matthew Jasper 已提交
515
                    } => {
516 517
                        self.visit_operand(cond, source_location);
                        self.visit_assert_message(msg, source_location);
518
                    }
J
John Kåre Alsaker 已提交
519

M
Matthew Jasper 已提交
520 521
                    TerminatorKind::Yield {
                        value,
522
                        resume: _,
523
                        resume_arg,
524
                        drop: _,
M
Matthew Jasper 已提交
525
                    } => {
526
                        self.visit_operand(value, source_location);
527 528
                        self.visit_place(
                            resume_arg,
529
                            PlaceContext::MutatingUse(MutatingUseContext::Yield),
530 531
                            source_location,
                        );
J
John Kåre Alsaker 已提交
532 533
                    }

A
Amanieu d'Antras 已提交
534 535 536 537
                    TerminatorKind::InlineAsm {
                        template: _,
                        operands,
                        options: _,
538
                        line_spans: _,
A
Amanieu d'Antras 已提交
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
                        destination: _,
                    } => {
                        for op in operands {
                            match op {
                                InlineAsmOperand::In { value, .. }
                                | InlineAsmOperand::Const { value } => {
                                    self.visit_operand(value, source_location);
                                }
                                InlineAsmOperand::Out { place, .. } => {
                                    if let Some(place) = place {
                                        self.visit_place(
                                            place,
                                            PlaceContext::MutatingUse(MutatingUseContext::Store),
                                            source_location,
                                        );
                                    }
                                }
                                InlineAsmOperand::InOut { in_value, out_place, .. } => {
                                    self.visit_operand(in_value, source_location);
                                    if let Some(out_place) = out_place {
                                        self.visit_place(
                                            out_place,
                                            PlaceContext::MutatingUse(MutatingUseContext::Store),
                                            source_location,
                                        );
                                    }
                                }
                                InlineAsmOperand::SymFn { value }
                                | InlineAsmOperand::SymStatic { value } => {
                                    self.visit_constant(value, source_location);
                                }
                            }
                        }
                    }
573 574 575 576
                }
            }

            fn super_assert_message(&mut self,
M
Matthew Jasper 已提交
577
                                    msg: & $($mutability)? AssertMessage<'tcx>,
578
                                    location: Location) {
R
Ralf Jung 已提交
579
                use crate::mir::AssertKind::*;
580 581 582 583 584
                match msg {
                    BoundsCheck { len, index } => {
                        self.visit_operand(len, location);
                        self.visit_operand(index, location);
                    }
585
                    Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
586
                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
587 588
                        // Nothing to visit
                    }
589 590
                }
            }
591

592
            fn super_rvalue(&mut self,
M
Matthew Jasper 已提交
593
                            rvalue: & $($mutability)? Rvalue<'tcx>,
594
                            location: Location) {
M
Matthew Jasper 已提交
595 596
                match rvalue {
                    Rvalue::Use(operand) => {
597
                        self.visit_operand(operand, location);
598
                    }
599

M
Matthew Jasper 已提交
600
                    Rvalue::Repeat(value, _) => {
601
                        self.visit_operand(value, location);
602
                    }
603

604 605
                    Rvalue::ThreadLocalRef(_) => {}

M
Matthew Jasper 已提交
606
                    Rvalue::Ref(r, bk, path) => {
607
                        self.visit_region(r, location);
608 609
                        let ctx = match bk {
                            BorrowKind::Shared => PlaceContext::NonMutatingUse(
610
                                NonMutatingUseContext::SharedBorrow
611 612
                            ),
                            BorrowKind::Shallow => PlaceContext::NonMutatingUse(
613
                                NonMutatingUseContext::ShallowBorrow
614 615
                            ),
                            BorrowKind::Unique => PlaceContext::NonMutatingUse(
616
                                NonMutatingUseContext::UniqueBorrow
617 618
                            ),
                            BorrowKind::Mut { .. } =>
619
                                PlaceContext::MutatingUse(MutatingUseContext::Borrow),
620 621
                        };
                        self.visit_place(path, ctx, location);
622
                    }
623

M
Matthew Jasper 已提交
624 625 626 627 628 629 630 631 632 633 634 635
                    Rvalue::AddressOf(m, path) => {
                        let ctx = match m {
                            Mutability::Mut => PlaceContext::MutatingUse(
                                MutatingUseContext::AddressOf
                            ),
                            Mutability::Not => PlaceContext::NonMutatingUse(
                                NonMutatingUseContext::AddressOf
                            ),
                        };
                        self.visit_place(path, ctx, location);
                    }

M
Matthew Jasper 已提交
636
                    Rvalue::Len(path) => {
637 638 639 640 641
                        self.visit_place(
                            path,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
642
                    }
643

M
Matthew Jasper 已提交
644
                    Rvalue::Cast(_cast_kind, operand, ty) => {
645
                        self.visit_operand(operand, location);
646
                        self.visit_ty(ty, TyContext::Location(location));
647
                    }
648

M
Matthew Jasper 已提交
649 650
                    Rvalue::BinaryOp(_bin_op, lhs, rhs)
                    | Rvalue::CheckedBinaryOp(_bin_op, lhs, rhs) => {
651 652
                        self.visit_operand(lhs, location);
                        self.visit_operand(rhs, location);
653
                    }
654

M
Matthew Jasper 已提交
655
                    Rvalue::UnaryOp(_un_op, op) => {
656
                        self.visit_operand(op, location);
657
                    }
658

M
Matthew Jasper 已提交
659
                    Rvalue::Discriminant(place) => {
660 661 662 663 664
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
665 666
                    }

M
Matthew Jasper 已提交
667
                    Rvalue::NullaryOp(_op, ty) => {
668
                        self.visit_ty(ty, TyContext::Location(location));
669
                    }
670

M
Matthew Jasper 已提交
671 672 673 674
                    Rvalue::Aggregate(kind, operands) => {
                        let kind = &$($mutability)? **kind;
                        match kind {
                            AggregateKind::Array(ty) => {
675
                                self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
676 677 678
                            }
                            AggregateKind::Tuple => {
                            }
M
Matthew Jasper 已提交
679 680 681 682 683 684 685
                            AggregateKind::Adt(
                                _adt_def,
                                _variant_index,
                                substs,
                                _user_substs,
                                _active_field_index
                            ) => {
686
                                self.visit_substs(substs, location);
N
Niko Matsakis 已提交
687
                            }
M
Matthew Jasper 已提交
688
                            AggregateKind::Closure(
689
                                _,
M
Matthew Jasper 已提交
690 691
                                closure_substs
                            ) => {
C
csmoe 已提交
692
                                self.visit_substs(closure_substs, location);
693
                            }
M
Matthew Jasper 已提交
694
                            AggregateKind::Generator(
695
                                _,
M
Matthew Jasper 已提交
696 697 698
                                generator_substs,
                                _movability,
                            ) => {
C
csmoe 已提交
699
                                self.visit_substs(generator_substs, location);
J
John Kåre Alsaker 已提交
700
                            }
701 702
                        }

N
Niko Matsakis 已提交
703
                        for operand in operands {
704
                            self.visit_operand(operand, location);
705 706
                        }
                    }
707 708 709
                }
            }

710
            fn super_operand(&mut self,
M
Matthew Jasper 已提交
711
                             operand: & $($mutability)? Operand<'tcx>,
712
                             location: Location) {
M
Matthew Jasper 已提交
713 714
                match operand {
                    Operand::Copy(place) => {
715 716 717 718 719
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                            location
                        );
720
                    }
M
Matthew Jasper 已提交
721
                    Operand::Move(place) => {
722 723 724 725 726
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                            location
                        );
727
                    }
M
Matthew Jasper 已提交
728
                    Operand::Constant(constant) => {
729
                        self.visit_constant(constant, location);
730
                    }
731 732 733
                }
            }

734
            fn super_ascribe_user_ty(&mut self,
M
Matthew Jasper 已提交
735 736
                                     place: & $($mutability)? Place<'tcx>,
                                     _variance: & $($mutability)? ty::Variance,
737
                                     user_ty: & $($mutability)? UserTypeProjection,
738
                                     location: Location) {
739 740 741 742 743
                self.visit_place(
                    place,
                    PlaceContext::NonUse(NonUseContext::AscribeUserTy),
                    location
                );
744
                self.visit_user_type_projection(user_ty);
D
David Wood 已提交
745 746
            }

747
            fn super_retag(&mut self,
M
Matthew Jasper 已提交
748 749
                           _kind: & $($mutability)? RetagKind,
                           place: & $($mutability)? Place<'tcx>,
750 751 752 753 754 755 756 757
                           location: Location) {
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Retag),
                    location,
                );
            }

758
            fn super_local_decl(&mut self,
759
                                local: Local,
M
Matthew Jasper 已提交
760
                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
761
                let LocalDecl {
N
Niko Matsakis 已提交
762
                    mutability: _,
M
Matthew Jasper 已提交
763 764 765
                    ty,
                    user_ty,
                    source_info,
766
                    internal: _,
M
Matthew Jasper 已提交
767
                    local_info: _,
768
                    is_block_tail: _,
M
Matthew Jasper 已提交
769
                } = local_decl;
N
Niko Matsakis 已提交
770

771 772
                self.visit_ty(ty, TyContext::LocalDecl {
                    local,
773
                    source_info: *source_info,
774
                });
775 776 777 778
                if let Some(user_ty) = user_ty {
                    for (user_ty, _) in & $($mutability)? user_ty.contents {
                        self.visit_user_type_projection(user_ty);
                    }
779
                }
780
                self.visit_source_info(source_info);
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
            }

            fn super_var_debug_info(&mut self,
                                    var_debug_info: & $($mutability)? VarDebugInfo<'tcx>) {
                let VarDebugInfo {
                    name: _,
                    source_info,
                    place,
                } = var_debug_info;

                self.visit_source_info(source_info);
                let location = START_BLOCK.start_location();
                self.visit_place(
                    place,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location,
                );
N
Niko Matsakis 已提交
798 799
            }

800
            fn super_source_scope(&mut self,
M
Matthew Jasper 已提交
801
                                      _scope: & $($mutability)? SourceScope) {
N
Niko Matsakis 已提交
802 803
            }

804
            fn super_constant(&mut self,
M
Matthew Jasper 已提交
805
                              constant: & $($mutability)? Constant<'tcx>,
806
                              location: Location) {
N
Niko Matsakis 已提交
807
                let Constant {
M
Matthew Jasper 已提交
808 809 810 811
                    span,
                    user_ty,
                    literal,
                } = constant;
N
Niko Matsakis 已提交
812 813

                self.visit_span(span);
814
                drop(user_ty); // no visit method for this
815
                self.visit_const(literal, location);
816 817
            }

M
Matthew Jasper 已提交
818
            fn super_span(&mut self, _span: & $($mutability)? Span) {
819
            }
N
Niko Matsakis 已提交
820

M
Matthew Jasper 已提交
821
            fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
822
                let SourceInfo {
M
Matthew Jasper 已提交
823 824 825
                    span,
                    scope,
                } = source_info;
826 827

                self.visit_span(span);
828
                self.visit_source_scope(scope);
829 830
            }

831 832
            fn super_user_type_projection(
                &mut self,
833
                _ty: & $($mutability)? UserTypeProjection,
834 835 836
            ) {
            }

N
Niko Matsakis 已提交
837 838
            fn super_user_type_annotation(
                &mut self,
D
David Wood 已提交
839
                _index: UserTypeAnnotationIndex,
M
Matthew Jasper 已提交
840
                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
N
Niko Matsakis 已提交
841
            ) {
M
Matthew Jasper 已提交
842 843
                self.visit_span(& $($mutability)? ty.span);
                self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
844 845
            }

F
flip1995 已提交
846
            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
N
Niko Matsakis 已提交
847 848
            }

M
Matthew Jasper 已提交
849
            fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
850 851
            }

O
Oliver Scherer 已提交
852
            fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
853 854
            }

C
csmoe 已提交
855
            fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
N
Niko Matsakis 已提交
856 857
            }

858
            // Convenience methods
859

860 861
            fn visit_location(
                &mut self,
D
Dylan MacKenzie 已提交
862
                body: &$($mutability)? Body<'tcx>,
863 864
                location: Location
            ) {
D
Dylan MacKenzie 已提交
865 866 867 868 869
                macro_rules! basic_blocks {
                    (mut) => (body.basic_blocks_mut());
                    () => (body.basic_blocks());
                };
                let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
870 871 872 873 874 875 876 877
                if basic_block.statements.len() == location.statement_index {
                    if let Some(ref $($mutability)? terminator) = basic_block.terminator {
                        self.visit_terminator(terminator, location)
                    }
                } else {
                    let statement = & $($mutability)?
                        basic_block.statements[location.statement_index];
                    self.visit_statement(statement, location)
878 879
                }
            }
880 881
        }
    }
882
}
883

884
macro_rules! visit_place_fns {
885
    (mut) => {
S
Santiago Pastorino 已提交
886 887
        fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;

888 889
        fn super_place(
            &mut self,
890 891 892
            place: &mut Place<'tcx>,
            context: PlaceContext,
            location: Location,
893
        ) {
894
            self.visit_local(&mut place.local, context, location);
895

896
            if let Some(new_projection) = self.process_projection(&place.projection, location) {
S
Santiago Pastorino 已提交
897
                place.projection = self.tcx().intern_place_elems(&new_projection);
898
            }
899 900 901 902
        }

        fn process_projection(
            &mut self,
903
            projection: &'a [PlaceElem<'tcx>],
904
            location: Location,
S
Santiago Pastorino 已提交
905
        ) -> Option<Vec<PlaceElem<'tcx>>> {
906
            let mut projection = Cow::Borrowed(projection);
907

908
            for i in 0..projection.len() {
B
Bastian Kauschke 已提交
909
                if let Some(&elem) = projection.get(i) {
910
                    if let Some(elem) = self.process_projection_elem(elem, location) {
S
Santiago Pastorino 已提交
911 912
                        // This converts the borrowed projection into `Cow::Owned(_)` and returns a
                        // clone of the projection so we can mutate and reintern later.
913 914 915 916 917 918 919 920
                        let vec = projection.to_mut();
                        vec[i] = elem;
                    }
                }
            }

            match projection {
                Cow::Borrowed(_) => None,
S
Santiago Pastorino 已提交
921
                Cow::Owned(vec) => Some(vec),
922
            }
923 924 925 926
        }

        fn process_projection_elem(
            &mut self,
B
Bastian Kauschke 已提交
927
            elem: PlaceElem<'tcx>,
928
            location: Location,
929
        ) -> Option<PlaceElem<'tcx>> {
930 931
            match elem {
                PlaceElem::Index(local) => {
B
Bastian Kauschke 已提交
932
                    let mut new_local = local;
933 934 935 936 937 938
                    self.visit_local(
                        &mut new_local,
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                        location,
                    );

B
Bastian Kauschke 已提交
939
                    if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
940 941 942 943 944 945 946
                }
                PlaceElem::Deref
                | PlaceElem::Field(..)
                | PlaceElem::ConstantIndex { .. }
                | PlaceElem::Subslice { .. }
                | PlaceElem::Downcast(..) => None,
            }
947
        }
948
    };
949

950
    () => {
951 952
        fn visit_projection(
            &mut self,
953
            local: Local,
954 955 956 957
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
958
            self.super_projection(local, projection, context, location);
959 960 961 962
        }

        fn visit_projection_elem(
            &mut self,
963
            local: Local,
964
            proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
965
            elem: PlaceElem<'tcx>,
966 967 968
            context: PlaceContext,
            location: Location,
        ) {
969
            self.super_projection_elem(local, proj_base, elem, context, location);
970 971
        }

972
        fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
973 974 975 976 977 978 979 980 981 982
            let mut context = context;

            if !place.projection.is_empty() {
                context = if context.is_mutating_use() {
                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
                } else {
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
                };
            }

983
            self.visit_local(&place.local, context, location);
984

985
            self.visit_projection(place.local, &place.projection, context, location);
986 987 988 989
        }

        fn super_projection(
            &mut self,
990
            local: Local,
991 992 993 994 995
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
            let mut cursor = projection;
B
Bastian Kauschke 已提交
996
            while let &[ref proj_base @ .., elem] = cursor {
997
                cursor = proj_base;
998
                self.visit_projection_elem(local, cursor, elem, context, location);
999 1000 1001 1002 1003
            }
        }

        fn super_projection_elem(
            &mut self,
1004
            _local: Local,
1005
            _proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
1006
            elem: PlaceElem<'tcx>,
1007 1008 1009 1010 1011 1012 1013 1014 1015
            _context: PlaceContext,
            location: Location,
        ) {
            match elem {
                ProjectionElem::Field(_field, ty) => {
                    self.visit_ty(ty, TyContext::Location(location));
                }
                ProjectionElem::Index(local) => {
                    self.visit_local(
B
Bastian Kauschke 已提交
1016
                        &local,
1017
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1018
                        location,
1019 1020
                    );
                }
1021 1022 1023 1024
                ProjectionElem::Deref
                | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
                | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
                | ProjectionElem::Downcast(_, _) => {}
1025 1026
            }
        }
1027
    };
1028 1029
}

1030
make_mir_visitor!(Visitor,);
M
Mark Rousskov 已提交
1031
make_mir_visitor!(MutVisitor, mut);
1032

S
Santiago Pastorino 已提交
1033 1034 1035 1036 1037
pub trait MirVisitable<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
M
Mark Rousskov 已提交
1038
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1039
        visitor.visit_statement(self, location)
S
Santiago Pastorino 已提交
1040 1041 1042 1043
    }
}

impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
M
Mark Rousskov 已提交
1044
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1045
        visitor.visit_terminator(self, location)
S
Santiago Pastorino 已提交
1046 1047 1048 1049
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
M
Mark Rousskov 已提交
1050
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1051
        visitor.visit_terminator(self.as_ref().unwrap(), location)
S
Santiago Pastorino 已提交
1052 1053 1054
    }
}

1055 1056
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
1057
#[derive(Debug)]
1058 1059 1060 1061 1062 1063 1064 1065 1066
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,
    },

1067 1068 1069
    /// The inferred type of a user type annotation.
    UserTy(Span),

N
Niko Matsakis 已提交
1070 1071
    /// The return type of the function.
    ReturnTy(SourceInfo),
1072

1073 1074
    YieldTy(SourceInfo),

N
Niko Matsakis 已提交
1075 1076
    /// A type found at some location.
    Location(Location),
1077 1078
}

1079
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1080
pub enum NonMutatingUseContext {
1081 1082 1083 1084 1085 1086 1087
    /// Being inspected in some way, like loading a len.
    Inspect,
    /// Consumed as part of an operand.
    Copy,
    /// Consumed as part of an operand.
    Move,
    /// Shared borrow.
1088
    SharedBorrow,
1089
    /// Shallow borrow.
1090
    ShallowBorrow,
1091
    /// Unique borrow.
1092
    UniqueBorrow,
M
Matthew Jasper 已提交
1093 1094
    /// AddressOf for *const pointer.
    AddressOf,
1095
    /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1096 1097 1098 1099 1100 1101 1102
    /// For example, the projection `x.y` is not marked as a mutation in these cases:
    ///
    ///     z = x.y;
    ///     f(&x.y);
    ///
    Projection,
}
1103

1104
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1105
pub enum MutatingUseContext {
1106 1107 1108 1109 1110
    /// Appears as LHS of an assignment.
    Store,
    /// 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.
1111
    AsmOutput,
1112
    /// Destination of a call.
1113
    Call,
1114 1115
    /// Destination of a yield.
    Yield,
1116
    /// Being dropped.
1117
    Drop,
1118
    /// Mutable borrow.
1119
    Borrow,
M
Matthew Jasper 已提交
1120 1121
    /// AddressOf for *mut pointer.
    AddressOf,
1122
    /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1123 1124 1125 1126 1127 1128
    /// For example, the projection `x.y` is marked as a mutation in these cases:
    ///
    ///     x.y = ...;
    ///     f(&mut x.y);
    ///
    Projection,
1129
    /// Retagging, a "Stacked Borrows" shadow state operation
1130
    Retag,
1131
}
1132

1133 1134 1135
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum NonUseContext {
    /// Starting a storage live range.
1136
    StorageLive,
1137
    /// Ending a storage live range.
1138
    StorageDead,
1139 1140
    /// User type annotation assertions for NLL.
    AscribeUserTy,
1141 1142
    /// The data of an user variable, for debug info.
    VarDebugInfo,
1143
}
1144

1145
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1146 1147 1148
pub enum PlaceContext {
    NonMutatingUse(NonMutatingUseContext),
    MutatingUse(MutatingUseContext),
1149 1150 1151
    NonUse(NonUseContext),
}

1152
impl PlaceContext {
1153
    /// Returns `true` if this place context represents a drop.
1154 1155
    pub fn is_drop(&self) -> bool {
        match *self {
1156 1157 1158 1159 1160 1161 1162 1163
            PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
            _ => false,
        }
    }

    /// Returns `true` if this place context represents a borrow.
    pub fn is_borrow(&self) -> bool {
        match *self {
1164 1165 1166 1167 1168
            PlaceContext::NonMutatingUse(
                NonMutatingUseContext::SharedBorrow
                | NonMutatingUseContext::ShallowBorrow
                | NonMutatingUseContext::UniqueBorrow,
            )
M
Mark Rousskov 已提交
1169
            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
1170 1171 1172 1173
            _ => false,
        }
    }

1174
    /// Returns `true` if this place context represents a storage live or storage dead marker.
1175 1176
    pub fn is_storage_marker(&self) -> bool {
        match *self {
1177
            PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => true,
1178 1179 1180 1181
            _ => false,
        }
    }

1182
    /// Returns `true` if this place context represents a storage live marker.
1183 1184
    pub fn is_storage_live_marker(&self) -> bool {
        match *self {
1185
            PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1186 1187 1188 1189
            _ => false,
        }
    }

1190
    /// Returns `true` if this place context represents a storage dead marker.
1191 1192
    pub fn is_storage_dead_marker(&self) -> bool {
        match *self {
1193
            PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1194 1195 1196 1197
            _ => false,
        }
    }

1198
    /// Returns `true` if this place context represents a use that potentially changes the value.
1199 1200
    pub fn is_mutating_use(&self) -> bool {
        match *self {
1201 1202
            PlaceContext::MutatingUse(..) => true,
            _ => false,
1203 1204 1205
        }
    }

1206
    /// Returns `true` if this place context represents a use that does not change the value.
1207 1208
    pub fn is_nonmutating_use(&self) -> bool {
        match *self {
1209 1210
            PlaceContext::NonMutatingUse(..) => true,
            _ => false,
1211 1212 1213
        }
    }

1214
    /// Returns `true` if this place context represents a use.
1215
    pub fn is_use(&self) -> bool {
1216 1217 1218 1219 1220 1221 1222 1223 1224
        match *self {
            PlaceContext::NonUse(..) => false,
            _ => true,
        }
    }

    /// Returns `true` if this place context represents an assignment statement.
    pub fn is_place_assignment(&self) -> bool {
        match *self {
1225 1226 1227 1228 1229
            PlaceContext::MutatingUse(
                MutatingUseContext::Store
                | MutatingUseContext::Call
                | MutatingUseContext::AsmOutput,
            ) => true,
1230 1231
            _ => false,
        }
1232 1233
    }
}