visit.rs 44.9 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
            }

111
            fn visit_assert_message(&mut self,
M
Matthew Jasper 已提交
112
                                    msg: & $($mutability)? AssertMessage<'tcx>,
113 114
                                    location: Location) {
                self.super_assert_message(msg, location);
115 116
            }

117
            fn visit_rvalue(&mut self,
M
Matthew Jasper 已提交
118
                            rvalue: & $($mutability)? Rvalue<'tcx>,
119 120
                            location: Location) {
                self.super_rvalue(rvalue, location);
N
Niko Matsakis 已提交
121 122
            }

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

129
            fn visit_ascribe_user_ty(&mut self,
M
Matthew Jasper 已提交
130 131
                                     place: & $($mutability)? Place<'tcx>,
                                     variance: & $($mutability)? ty::Variance,
132
                                     user_ty: & $($mutability)? UserTypeProjection,
133
                                     location: Location) {
134
                self.super_ascribe_user_ty(place, variance, user_ty, location);
D
David Wood 已提交
135 136
            }

137
            fn visit_retag(&mut self,
M
Matthew Jasper 已提交
138 139
                           kind: & $($mutability)? RetagKind,
                           place: & $($mutability)? Place<'tcx>,
140
                           location: Location) {
141
                self.super_retag(kind, place, location);
142 143
            }

144
            fn visit_place(&mut self,
M
Matthew Jasper 已提交
145
                            place: & $($mutability)? Place<'tcx>,
146
                            context: PlaceContext,
147
                            location: Location) {
148
                self.super_place(place, context, location);
N
Niko Matsakis 已提交
149 150
            }

151
            visit_place_fns!($($mutability)?);
152

153
            fn visit_constant(&mut self,
M
Matthew Jasper 已提交
154
                              constant: & $($mutability)? Constant<'tcx>,
155 156
                              location: Location) {
                self.super_constant(constant, location);
N
Niko Matsakis 已提交
157 158
            }

159
            fn visit_span(&mut self,
M
Matthew Jasper 已提交
160
                          span: & $($mutability)? Span) {
161
                self.super_span(span);
N
Niko Matsakis 已提交
162 163
            }

164
            fn visit_source_info(&mut self,
M
Matthew Jasper 已提交
165
                                 source_info: & $($mutability)? SourceInfo) {
166 167 168
                self.super_source_info(source_info);
            }

N
Niko Matsakis 已提交
169
            fn visit_ty(&mut self,
F
flip1995 已提交
170
                        ty: $(& $mutability)? Ty<'tcx>,
171
                        _: TyContext) {
N
Niko Matsakis 已提交
172 173 174
                self.super_ty(ty);
            }

175 176
            fn visit_user_type_projection(
                &mut self,
177
                ty: & $($mutability)? UserTypeProjection,
178 179 180 181
            ) {
                self.super_user_type_projection(ty);
            }

N
Niko Matsakis 已提交
182 183
            fn visit_user_type_annotation(
                &mut self,
D
David Wood 已提交
184
                index: UserTypeAnnotationIndex,
M
Matthew Jasper 已提交
185
                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
N
Niko Matsakis 已提交
186
            ) {
D
David Wood 已提交
187
                self.super_user_type_annotation(index, ty);
188 189
            }

190
            fn visit_region(&mut self,
M
Matthew Jasper 已提交
191
                            region: & $($mutability)? ty::Region<'tcx>,
192 193 194 195 196
                            _: Location) {
                self.super_region(region);
            }

            fn visit_const(&mut self,
O
Oliver Scherer 已提交
197
                           constant: & $($mutability)? &'tcx ty::Const<'tcx>,
198 199 200 201
                           _: Location) {
                self.super_const(constant);
            }

N
Niko Matsakis 已提交
202
            fn visit_substs(&mut self,
C
csmoe 已提交
203
                            substs: & $($mutability)? SubstsRef<'tcx>,
204
                            _: Location) {
N
Niko Matsakis 已提交
205 206 207
                self.super_substs(substs);
            }

208
            fn visit_local_decl(&mut self,
209
                                local: Local,
M
Matthew Jasper 已提交
210
                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
211
                self.super_local_decl(local, local_decl);
N
Niko Matsakis 已提交
212 213
            }

214 215 216 217 218
            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 已提交
219
            fn visit_local(&mut self,
M
Matthew Jasper 已提交
220
                            _local: & $($mutability)? Local,
221
                            _context: PlaceContext,
222
                            _location: Location) {
J
John Kåre Alsaker 已提交
223 224
            }

225
            fn visit_source_scope(&mut self,
M
Matthew Jasper 已提交
226
                                      scope: & $($mutability)? SourceScope) {
227
                self.super_source_scope(scope);
N
Niko Matsakis 已提交
228 229
            }

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

233 234
            fn super_body(
                &mut self,
D
Dylan MacKenzie 已提交
235
                body: &$($mutability)? Body<'tcx>,
236
            ) {
237 238
                let span = body.span;
                if let Some(yield_ty) = &$($mutability)? body.yield_ty {
239 240 241 242
                    self.visit_ty(
                        yield_ty,
                        TyContext::YieldTy(SourceInfo::outermost(span))
                    );
243 244
                }

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

256
                for scope in &$($mutability)? body.source_scopes {
257
                    self.visit_source_scope_data(scope);
N
Niko Matsakis 已提交
258 259
                }

260 261 262 263
                self.visit_ty(
                    &$($mutability)? body.return_ty(),
                    TyContext::ReturnTy(SourceInfo::outermost(body.span))
                );
N
Niko Matsakis 已提交
264

265 266
                for local in body.local_decls.indices() {
                    self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
N
Niko Matsakis 已提交
267 268
                }

269
                macro_rules! type_annotations {
270 271
                    (mut) => (body.user_type_annotations.iter_enumerated_mut());
                    () => (body.user_type_annotations.iter_enumerated());
272 273
                };

M
Matthew Jasper 已提交
274
                for (index, annotation) in type_annotations!($($mutability)?) {
D
David Wood 已提交
275 276 277 278 279
                    self.visit_user_type_annotation(
                        index, annotation
                    );
                }

280 281 282 283
                for var_debug_info in &$($mutability)? body.var_debug_info {
                    self.visit_var_debug_info(var_debug_info);
                }

284
                self.visit_span(&$($mutability)? body.span);
285

286
                for const_ in &$($mutability)? body.required_consts {
287 288 289
                    let location = START_BLOCK.start_location();
                    self.visit_constant(const_, location);
                }
N
Niko Matsakis 已提交
290 291
            }

292 293
            fn super_basic_block_data(&mut self,
                                      block: BasicBlock,
M
Matthew Jasper 已提交
294
                                      data: & $($mutability)? BasicBlockData<'tcx>) {
N
Niko Matsakis 已提交
295
                let BasicBlockData {
M
Matthew Jasper 已提交
296 297
                    statements,
                    terminator,
N
Niko Matsakis 已提交
298
                    is_cleanup: _
M
Matthew Jasper 已提交
299
                } = data;
N
Niko Matsakis 已提交
300

301
                let mut index = 0;
N
Niko Matsakis 已提交
302
                for statement in statements {
303
                    let location = Location { block: block, statement_index: index };
304
                    self.visit_statement(statement, location);
305
                    index += 1;
N
Niko Matsakis 已提交
306 307
                }

M
Matthew Jasper 已提交
308
                if let Some(terminator) = terminator {
309
                    let location = Location { block: block, statement_index: index };
310
                    self.visit_terminator(terminator, location);
311
                }
N
Niko Matsakis 已提交
312 313
            }

M
Matthew Jasper 已提交
314
            fn super_source_scope_data(&mut self, scope_data: & $($mutability)? SourceScopeData) {
315
                let SourceScopeData {
M
Matthew Jasper 已提交
316 317
                    span,
                    parent_scope,
318
                    local_data: _,
M
Matthew Jasper 已提交
319
                } = scope_data;
N
Niko Matsakis 已提交
320

321
                self.visit_span(span);
M
Matthew Jasper 已提交
322
                if let Some(parent_scope) = parent_scope {
323
                    self.visit_source_scope(parent_scope);
N
Niko Matsakis 已提交
324 325 326
                }
            }

327
            fn super_statement(&mut self,
M
Matthew Jasper 已提交
328
                               statement: & $($mutability)? Statement<'tcx>,
329
                               location: Location) {
N
Niko Matsakis 已提交
330
                let Statement {
M
Matthew Jasper 已提交
331 332 333
                    source_info,
                    kind,
                } = statement;
N
Niko Matsakis 已提交
334

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

396
            fn super_assign(&mut self,
M
Matthew Jasper 已提交
397 398
                            place: &$($mutability)? Place<'tcx>,
                            rvalue: &$($mutability)? Rvalue<'tcx>,
399
                            location: Location) {
400 401 402 403 404
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Store),
                    location
                );
405
                self.visit_rvalue(rvalue, location);
406
            }
407

408
            fn super_terminator(&mut self,
M
Matthew Jasper 已提交
409
                                terminator: &$($mutability)? Terminator<'tcx>,
410
                                source_location: Location) {
M
Matthew Jasper 已提交
411
                let Terminator { source_info, kind } = terminator;
N
Niko Matsakis 已提交
412

413
                self.visit_source_info(source_info);
M
Matthew Jasper 已提交
414
                match kind {
415 416 417 418 419
                    TerminatorKind::Goto { .. } |
                    TerminatorKind::Resume |
                    TerminatorKind::Abort |
                    TerminatorKind::GeneratorDrop |
                    TerminatorKind::Unreachable |
R
Ralf Jung 已提交
420
                    TerminatorKind::FalseEdge { .. } |
421
                    TerminatorKind::FalseUnwind { .. } => {
422
                    }
423

424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
                    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 已提交
441 442 443 444
                    TerminatorKind::SwitchInt {
                        discr,
                        switch_ty,
                        values: _,
445
                        targets: _
M
Matthew Jasper 已提交
446
                    } => {
447
                        self.visit_operand(discr, source_location);
448
                        self.visit_ty(switch_ty, TyContext::Location(source_location));
449
                    }
450

M
Matthew Jasper 已提交
451
                    TerminatorKind::Drop {
452
                        place,
453 454
                        target: _,
                        unwind: _,
M
Matthew Jasper 已提交
455
                    } => {
456
                        self.visit_place(
457
                            place,
458 459 460
                            PlaceContext::MutatingUse(MutatingUseContext::Drop),
                            source_location
                        );
461 462
                    }

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

M
Matthew Jasper 已提交
477 478 479 480
                    TerminatorKind::Call {
                        func,
                        args,
                        destination,
481
                        cleanup: _,
M
Matthew Jasper 已提交
482
                        from_hir_call: _,
483
                        fn_span: _
M
Matthew Jasper 已提交
484
                    } => {
485
                        self.visit_operand(func, source_location);
486
                        for arg in args {
487
                            self.visit_operand(arg, source_location);
488
                        }
489
                        if let Some((destination, _)) = destination {
490 491 492 493 494
                            self.visit_place(
                                destination,
                                PlaceContext::MutatingUse(MutatingUseContext::Call),
                                source_location
                            );
495 496
                        }
                    }
497

M
Matthew Jasper 已提交
498 499 500 501
                    TerminatorKind::Assert {
                        cond,
                        expected: _,
                        msg,
502 503
                        target: _,
                        cleanup: _,
M
Matthew Jasper 已提交
504
                    } => {
505 506
                        self.visit_operand(cond, source_location);
                        self.visit_assert_message(msg, source_location);
507
                    }
J
John Kåre Alsaker 已提交
508

M
Matthew Jasper 已提交
509 510
                    TerminatorKind::Yield {
                        value,
511
                        resume: _,
512
                        resume_arg,
513
                        drop: _,
M
Matthew Jasper 已提交
514
                    } => {
515
                        self.visit_operand(value, source_location);
516 517
                        self.visit_place(
                            resume_arg,
518
                            PlaceContext::MutatingUse(MutatingUseContext::Yield),
519 520
                            source_location,
                        );
J
John Kåre Alsaker 已提交
521 522
                    }

A
Amanieu d'Antras 已提交
523 524 525 526
                    TerminatorKind::InlineAsm {
                        template: _,
                        operands,
                        options: _,
527
                        line_spans: _,
A
Amanieu d'Antras 已提交
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
                        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,
                                        );
                                    }
                                }
555
                                InlineAsmOperand::SymFn { value } => {
A
Amanieu d'Antras 已提交
556 557
                                    self.visit_constant(value, source_location);
                                }
558
                                InlineAsmOperand::SymStatic { def_id: _ } => {}
A
Amanieu d'Antras 已提交
559 560 561
                            }
                        }
                    }
562 563 564 565
                }
            }

            fn super_assert_message(&mut self,
M
Matthew Jasper 已提交
566
                                    msg: & $($mutability)? AssertMessage<'tcx>,
567
                                    location: Location) {
R
Ralf Jung 已提交
568
                use crate::mir::AssertKind::*;
569 570 571 572 573
                match msg {
                    BoundsCheck { len, index } => {
                        self.visit_operand(len, location);
                        self.visit_operand(index, location);
                    }
574
                    Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
575
                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
576 577
                        // Nothing to visit
                    }
578 579
                }
            }
580

581
            fn super_rvalue(&mut self,
M
Matthew Jasper 已提交
582
                            rvalue: & $($mutability)? Rvalue<'tcx>,
583
                            location: Location) {
M
Matthew Jasper 已提交
584 585
                match rvalue {
                    Rvalue::Use(operand) => {
586
                        self.visit_operand(operand, location);
587
                    }
588

M
Matthew Jasper 已提交
589
                    Rvalue::Repeat(value, _) => {
590
                        self.visit_operand(value, location);
591
                    }
592

593 594
                    Rvalue::ThreadLocalRef(_) => {}

M
Matthew Jasper 已提交
595
                    Rvalue::Ref(r, bk, path) => {
596
                        self.visit_region(r, location);
597 598
                        let ctx = match bk {
                            BorrowKind::Shared => PlaceContext::NonMutatingUse(
599
                                NonMutatingUseContext::SharedBorrow
600 601
                            ),
                            BorrowKind::Shallow => PlaceContext::NonMutatingUse(
602
                                NonMutatingUseContext::ShallowBorrow
603 604
                            ),
                            BorrowKind::Unique => PlaceContext::NonMutatingUse(
605
                                NonMutatingUseContext::UniqueBorrow
606 607
                            ),
                            BorrowKind::Mut { .. } =>
608
                                PlaceContext::MutatingUse(MutatingUseContext::Borrow),
609 610
                        };
                        self.visit_place(path, ctx, location);
611
                    }
612

M
Matthew Jasper 已提交
613 614 615 616 617 618 619 620 621 622 623 624
                    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 已提交
625
                    Rvalue::Len(path) => {
626 627 628 629 630
                        self.visit_place(
                            path,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
631
                    }
632

M
Matthew Jasper 已提交
633
                    Rvalue::Cast(_cast_kind, operand, ty) => {
634
                        self.visit_operand(operand, location);
635
                        self.visit_ty(ty, TyContext::Location(location));
636
                    }
637

M
Matthew Jasper 已提交
638 639
                    Rvalue::BinaryOp(_bin_op, lhs, rhs)
                    | Rvalue::CheckedBinaryOp(_bin_op, lhs, rhs) => {
640 641
                        self.visit_operand(lhs, location);
                        self.visit_operand(rhs, location);
642
                    }
643

M
Matthew Jasper 已提交
644
                    Rvalue::UnaryOp(_un_op, op) => {
645
                        self.visit_operand(op, location);
646
                    }
647

M
Matthew Jasper 已提交
648
                    Rvalue::Discriminant(place) => {
649 650 651 652 653
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
654 655
                    }

M
Matthew Jasper 已提交
656
                    Rvalue::NullaryOp(_op, ty) => {
657
                        self.visit_ty(ty, TyContext::Location(location));
658
                    }
659

M
Matthew Jasper 已提交
660 661 662 663
                    Rvalue::Aggregate(kind, operands) => {
                        let kind = &$($mutability)? **kind;
                        match kind {
                            AggregateKind::Array(ty) => {
664
                                self.visit_ty(ty, TyContext::Location(location));
N
Niko Matsakis 已提交
665 666 667
                            }
                            AggregateKind::Tuple => {
                            }
M
Matthew Jasper 已提交
668 669 670 671 672 673 674
                            AggregateKind::Adt(
                                _adt_def,
                                _variant_index,
                                substs,
                                _user_substs,
                                _active_field_index
                            ) => {
675
                                self.visit_substs(substs, location);
N
Niko Matsakis 已提交
676
                            }
M
Matthew Jasper 已提交
677
                            AggregateKind::Closure(
678
                                _,
M
Matthew Jasper 已提交
679 680
                                closure_substs
                            ) => {
C
csmoe 已提交
681
                                self.visit_substs(closure_substs, location);
682
                            }
M
Matthew Jasper 已提交
683
                            AggregateKind::Generator(
684
                                _,
M
Matthew Jasper 已提交
685 686 687
                                generator_substs,
                                _movability,
                            ) => {
C
csmoe 已提交
688
                                self.visit_substs(generator_substs, location);
J
John Kåre Alsaker 已提交
689
                            }
690 691
                        }

N
Niko Matsakis 已提交
692
                        for operand in operands {
693
                            self.visit_operand(operand, location);
694 695
                        }
                    }
696 697 698
                }
            }

699
            fn super_operand(&mut self,
M
Matthew Jasper 已提交
700
                             operand: & $($mutability)? Operand<'tcx>,
701
                             location: Location) {
M
Matthew Jasper 已提交
702 703
                match operand {
                    Operand::Copy(place) => {
704 705 706 707 708
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                            location
                        );
709
                    }
M
Matthew Jasper 已提交
710
                    Operand::Move(place) => {
711 712 713 714 715
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                            location
                        );
716
                    }
M
Matthew Jasper 已提交
717
                    Operand::Constant(constant) => {
718
                        self.visit_constant(constant, location);
719
                    }
720 721 722
                }
            }

723
            fn super_ascribe_user_ty(&mut self,
M
Matthew Jasper 已提交
724 725
                                     place: & $($mutability)? Place<'tcx>,
                                     _variance: & $($mutability)? ty::Variance,
726
                                     user_ty: & $($mutability)? UserTypeProjection,
727
                                     location: Location) {
728 729 730 731 732
                self.visit_place(
                    place,
                    PlaceContext::NonUse(NonUseContext::AscribeUserTy),
                    location
                );
733
                self.visit_user_type_projection(user_ty);
D
David Wood 已提交
734 735
            }

736
            fn super_retag(&mut self,
M
Matthew Jasper 已提交
737 738
                           _kind: & $($mutability)? RetagKind,
                           place: & $($mutability)? Place<'tcx>,
739 740 741 742 743 744 745 746
                           location: Location) {
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Retag),
                    location,
                );
            }

747
            fn super_local_decl(&mut self,
748
                                local: Local,
M
Matthew Jasper 已提交
749
                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
750
                let LocalDecl {
N
Niko Matsakis 已提交
751
                    mutability: _,
M
Matthew Jasper 已提交
752 753 754
                    ty,
                    user_ty,
                    source_info,
755
                    internal: _,
M
Matthew Jasper 已提交
756
                    local_info: _,
757
                    is_block_tail: _,
M
Matthew Jasper 已提交
758
                } = local_decl;
N
Niko Matsakis 已提交
759

760 761
                self.visit_ty(ty, TyContext::LocalDecl {
                    local,
762
                    source_info: *source_info,
763
                });
764 765 766 767
                if let Some(user_ty) = user_ty {
                    for (user_ty, _) in & $($mutability)? user_ty.contents {
                        self.visit_user_type_projection(user_ty);
                    }
768
                }
769
                self.visit_source_info(source_info);
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
            }

            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 已提交
787 788
            }

789
            fn super_source_scope(&mut self,
M
Matthew Jasper 已提交
790
                                      _scope: & $($mutability)? SourceScope) {
N
Niko Matsakis 已提交
791 792
            }

793
            fn super_constant(&mut self,
M
Matthew Jasper 已提交
794
                              constant: & $($mutability)? Constant<'tcx>,
795
                              location: Location) {
N
Niko Matsakis 已提交
796
                let Constant {
M
Matthew Jasper 已提交
797 798 799 800
                    span,
                    user_ty,
                    literal,
                } = constant;
N
Niko Matsakis 已提交
801 802

                self.visit_span(span);
803
                drop(user_ty); // no visit method for this
804
                self.visit_const(literal, location);
805 806
            }

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

M
Matthew Jasper 已提交
810
            fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
811
                let SourceInfo {
M
Matthew Jasper 已提交
812 813 814
                    span,
                    scope,
                } = source_info;
815 816

                self.visit_span(span);
817
                self.visit_source_scope(scope);
818 819
            }

820 821
            fn super_user_type_projection(
                &mut self,
822
                _ty: & $($mutability)? UserTypeProjection,
823 824 825
            ) {
            }

N
Niko Matsakis 已提交
826 827
            fn super_user_type_annotation(
                &mut self,
D
David Wood 已提交
828
                _index: UserTypeAnnotationIndex,
M
Matthew Jasper 已提交
829
                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
N
Niko Matsakis 已提交
830
            ) {
M
Matthew Jasper 已提交
831 832
                self.visit_span(& $($mutability)? ty.span);
                self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
833 834
            }

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

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

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

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

847
            // Convenience methods
848

849 850
            fn visit_location(
                &mut self,
D
Dylan MacKenzie 已提交
851
                body: &$($mutability)? Body<'tcx>,
852 853
                location: Location
            ) {
D
Dylan MacKenzie 已提交
854 855 856 857 858
                macro_rules! basic_blocks {
                    (mut) => (body.basic_blocks_mut());
                    () => (body.basic_blocks());
                };
                let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
859 860 861 862 863 864 865 866
                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)
867 868
                }
            }
869 870
        }
    }
871
}
872

873
macro_rules! visit_place_fns {
874
    (mut) => {
S
Santiago Pastorino 已提交
875 876
        fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;

877 878
        fn super_place(
            &mut self,
879 880 881
            place: &mut Place<'tcx>,
            context: PlaceContext,
            location: Location,
882
        ) {
883
            self.visit_local(&mut place.local, context, location);
884

885
            if let Some(new_projection) = self.process_projection(&place.projection, location) {
S
Santiago Pastorino 已提交
886
                place.projection = self.tcx().intern_place_elems(&new_projection);
887
            }
888 889 890 891
        }

        fn process_projection(
            &mut self,
892
            projection: &'a [PlaceElem<'tcx>],
893
            location: Location,
S
Santiago Pastorino 已提交
894
        ) -> Option<Vec<PlaceElem<'tcx>>> {
895
            let mut projection = Cow::Borrowed(projection);
896

897
            for i in 0..projection.len() {
B
Bastian Kauschke 已提交
898
                if let Some(&elem) = projection.get(i) {
899
                    if let Some(elem) = self.process_projection_elem(elem, location) {
S
Santiago Pastorino 已提交
900 901
                        // This converts the borrowed projection into `Cow::Owned(_)` and returns a
                        // clone of the projection so we can mutate and reintern later.
902 903 904 905 906 907 908 909
                        let vec = projection.to_mut();
                        vec[i] = elem;
                    }
                }
            }

            match projection {
                Cow::Borrowed(_) => None,
S
Santiago Pastorino 已提交
910
                Cow::Owned(vec) => Some(vec),
911
            }
912 913 914 915
        }

        fn process_projection_elem(
            &mut self,
B
Bastian Kauschke 已提交
916
            elem: PlaceElem<'tcx>,
917
            location: Location,
918
        ) -> Option<PlaceElem<'tcx>> {
919 920
            match elem {
                PlaceElem::Index(local) => {
B
Bastian Kauschke 已提交
921
                    let mut new_local = local;
922 923 924 925 926 927
                    self.visit_local(
                        &mut new_local,
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                        location,
                    );

B
Bastian Kauschke 已提交
928
                    if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
929 930 931 932 933 934 935
                }
                PlaceElem::Deref
                | PlaceElem::Field(..)
                | PlaceElem::ConstantIndex { .. }
                | PlaceElem::Subslice { .. }
                | PlaceElem::Downcast(..) => None,
            }
936
        }
937
    };
938

939
    () => {
940 941
        fn visit_projection(
            &mut self,
942
            local: Local,
943 944 945 946
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
947
            self.super_projection(local, projection, context, location);
948 949 950 951
        }

        fn visit_projection_elem(
            &mut self,
952
            local: Local,
953
            proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
954
            elem: PlaceElem<'tcx>,
955 956 957
            context: PlaceContext,
            location: Location,
        ) {
958
            self.super_projection_elem(local, proj_base, elem, context, location);
959 960
        }

961
        fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
962 963 964 965 966 967 968 969 970 971
            let mut context = context;

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

972
            self.visit_local(&place.local, context, location);
973

974
            self.visit_projection(place.local, &place.projection, context, location);
975 976 977 978
        }

        fn super_projection(
            &mut self,
979
            local: Local,
980 981 982 983 984
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
            let mut cursor = projection;
B
Bastian Kauschke 已提交
985
            while let &[ref proj_base @ .., elem] = cursor {
986
                cursor = proj_base;
987
                self.visit_projection_elem(local, cursor, elem, context, location);
988 989 990 991 992
            }
        }

        fn super_projection_elem(
            &mut self,
993
            _local: Local,
994
            _proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
995
            elem: PlaceElem<'tcx>,
996 997 998 999 1000 1001 1002 1003 1004
            _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 已提交
1005
                        &local,
1006
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1007
                        location,
1008 1009
                    );
                }
1010 1011 1012 1013
                ProjectionElem::Deref
                | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
                | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
                | ProjectionElem::Downcast(_, _) => {}
1014 1015
            }
        }
1016
    };
1017 1018
}

1019
make_mir_visitor!(Visitor,);
M
Mark Rousskov 已提交
1020
make_mir_visitor!(MutVisitor, mut);
1021

S
Santiago Pastorino 已提交
1022 1023 1024 1025 1026
pub trait MirVisitable<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
M
Mark Rousskov 已提交
1027
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1028
        visitor.visit_statement(self, location)
S
Santiago Pastorino 已提交
1029 1030 1031 1032
    }
}

impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
M
Mark Rousskov 已提交
1033
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1034
        visitor.visit_terminator(self, location)
S
Santiago Pastorino 已提交
1035 1036 1037 1038
    }
}

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

1044 1045
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
1046
#[derive(Debug)]
1047 1048 1049 1050 1051 1052 1053 1054 1055
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,
    },

1056 1057 1058
    /// The inferred type of a user type annotation.
    UserTy(Span),

N
Niko Matsakis 已提交
1059 1060
    /// The return type of the function.
    ReturnTy(SourceInfo),
1061

1062 1063
    YieldTy(SourceInfo),

N
Niko Matsakis 已提交
1064 1065
    /// A type found at some location.
    Location(Location),
1066 1067
}

1068
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1069
pub enum NonMutatingUseContext {
1070 1071 1072 1073 1074 1075 1076
    /// 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.
1077
    SharedBorrow,
1078
    /// Shallow borrow.
1079
    ShallowBorrow,
1080
    /// Unique borrow.
1081
    UniqueBorrow,
M
Matthew Jasper 已提交
1082 1083
    /// AddressOf for *const pointer.
    AddressOf,
1084
    /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1085 1086 1087 1088 1089 1090 1091
    /// For example, the projection `x.y` is not marked as a mutation in these cases:
    ///
    ///     z = x.y;
    ///     f(&x.y);
    ///
    Projection,
}
1092

1093
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1094
pub enum MutatingUseContext {
1095 1096 1097 1098 1099
    /// 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.
1100
    AsmOutput,
1101
    /// Destination of a call.
1102
    Call,
1103 1104
    /// Destination of a yield.
    Yield,
1105
    /// Being dropped.
1106
    Drop,
1107
    /// Mutable borrow.
1108
    Borrow,
M
Matthew Jasper 已提交
1109 1110
    /// AddressOf for *mut pointer.
    AddressOf,
1111
    /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1112 1113 1114 1115 1116 1117
    /// For example, the projection `x.y` is marked as a mutation in these cases:
    ///
    ///     x.y = ...;
    ///     f(&mut x.y);
    ///
    Projection,
1118
    /// Retagging, a "Stacked Borrows" shadow state operation
1119
    Retag,
1120
}
1121

1122 1123 1124
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum NonUseContext {
    /// Starting a storage live range.
1125
    StorageLive,
1126
    /// Ending a storage live range.
1127
    StorageDead,
1128 1129
    /// User type annotation assertions for NLL.
    AscribeUserTy,
1130 1131
    /// The data of an user variable, for debug info.
    VarDebugInfo,
1132
}
1133

1134
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1135 1136 1137
pub enum PlaceContext {
    NonMutatingUse(NonMutatingUseContext),
    MutatingUse(MutatingUseContext),
1138 1139 1140
    NonUse(NonUseContext),
}

1141
impl PlaceContext {
1142
    /// Returns `true` if this place context represents a drop.
1143 1144
    pub fn is_drop(&self) -> bool {
        match *self {
1145 1146 1147 1148 1149 1150 1151 1152
            PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
            _ => false,
        }
    }

    /// Returns `true` if this place context represents a borrow.
    pub fn is_borrow(&self) -> bool {
        match *self {
1153 1154 1155 1156 1157
            PlaceContext::NonMutatingUse(
                NonMutatingUseContext::SharedBorrow
                | NonMutatingUseContext::ShallowBorrow
                | NonMutatingUseContext::UniqueBorrow,
            )
M
Mark Rousskov 已提交
1158
            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
1159 1160 1161 1162
            _ => false,
        }
    }

1163
    /// Returns `true` if this place context represents a storage live or storage dead marker.
1164 1165
    pub fn is_storage_marker(&self) -> bool {
        match *self {
1166
            PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => true,
1167 1168 1169 1170
            _ => false,
        }
    }

1171
    /// Returns `true` if this place context represents a storage live marker.
1172 1173
    pub fn is_storage_live_marker(&self) -> bool {
        match *self {
1174
            PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1175 1176 1177 1178
            _ => false,
        }
    }

1179
    /// Returns `true` if this place context represents a storage dead marker.
1180 1181
    pub fn is_storage_dead_marker(&self) -> bool {
        match *self {
1182
            PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1183 1184 1185 1186
            _ => false,
        }
    }

1187
    /// Returns `true` if this place context represents a use that potentially changes the value.
1188 1189
    pub fn is_mutating_use(&self) -> bool {
        match *self {
1190 1191
            PlaceContext::MutatingUse(..) => true,
            _ => false,
1192 1193 1194
        }
    }

1195
    /// Returns `true` if this place context represents a use that does not change the value.
1196 1197
    pub fn is_nonmutating_use(&self) -> bool {
        match *self {
1198 1199
            PlaceContext::NonMutatingUse(..) => true,
            _ => false,
1200 1201 1202
        }
    }

1203
    /// Returns `true` if this place context represents a use.
1204
    pub fn is_use(&self) -> bool {
1205 1206 1207 1208 1209 1210 1211 1212 1213
        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 {
1214 1215 1216 1217 1218
            PlaceContext::MutatingUse(
                MutatingUseContext::Store
                | MutatingUseContext::Call
                | MutatingUseContext::AsmOutput,
            ) => true,
1219 1220
            _ => false,
        }
1221 1222
    }
}