visit.rs 45.7 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 138 139 140 141 142
            fn visit_coverage(&mut self,
                              coverage: & $($mutability)? Coverage,
                              location: Location) {
                self.super_coverage(coverage, location);
            }

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 399 400 401 402 403
                    StatementKind::Coverage(coverage) => {
                        self.visit_coverage(
                            coverage,
                            location
                        )
                    }
404
                    StatementKind::Nop => {}
405
                }
N
Niko Matsakis 已提交
406
            }
407

408
            fn super_assign(&mut self,
M
Matthew Jasper 已提交
409 410
                            place: &$($mutability)? Place<'tcx>,
                            rvalue: &$($mutability)? Rvalue<'tcx>,
411
                            location: Location) {
412 413 414 415 416
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Store),
                    location
                );
417
                self.visit_rvalue(rvalue, location);
418
            }
419

420
            fn super_terminator(&mut self,
M
Matthew Jasper 已提交
421
                                terminator: &$($mutability)? Terminator<'tcx>,
422
                                location: Location) {
M
Matthew Jasper 已提交
423
                let Terminator { source_info, kind } = terminator;
N
Niko Matsakis 已提交
424

425
                self.visit_source_info(source_info);
M
Matthew Jasper 已提交
426
                match kind {
427 428 429 430 431
                    TerminatorKind::Goto { .. } |
                    TerminatorKind::Resume |
                    TerminatorKind::Abort |
                    TerminatorKind::GeneratorDrop |
                    TerminatorKind::Unreachable |
R
Ralf Jung 已提交
432
                    TerminatorKind::FalseEdge { .. } |
433
                    TerminatorKind::FalseUnwind { .. } => {
434
                    }
435

436 437 438 439 440 441 442
                    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),
443
                            location,
444 445 446 447 448 449 450 451 452
                        );

                        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 460
                        self.visit_operand(discr, location);
                        self.visit_ty(switch_ty, TyContext::Location(location));
461
                    }
462

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

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

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

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

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

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

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

599
            fn super_rvalue(&mut self,
M
Matthew Jasper 已提交
600
                            rvalue: & $($mutability)? Rvalue<'tcx>,
601
                            location: Location) {
M
Matthew Jasper 已提交
602 603
                match rvalue {
                    Rvalue::Use(operand) => {
604
                        self.visit_operand(operand, location);
605
                    }
606

M
Matthew Jasper 已提交
607
                    Rvalue::Repeat(value, _) => {
608
                        self.visit_operand(value, location);
609
                    }
610

611 612
                    Rvalue::ThreadLocalRef(_) => {}

M
Matthew Jasper 已提交
613
                    Rvalue::Ref(r, bk, path) => {
614
                        self.visit_region(r, location);
615 616
                        let ctx = match bk {
                            BorrowKind::Shared => PlaceContext::NonMutatingUse(
617
                                NonMutatingUseContext::SharedBorrow
618 619
                            ),
                            BorrowKind::Shallow => PlaceContext::NonMutatingUse(
620
                                NonMutatingUseContext::ShallowBorrow
621 622
                            ),
                            BorrowKind::Unique => PlaceContext::NonMutatingUse(
623
                                NonMutatingUseContext::UniqueBorrow
624 625
                            ),
                            BorrowKind::Mut { .. } =>
626
                                PlaceContext::MutatingUse(MutatingUseContext::Borrow),
627 628
                        };
                        self.visit_place(path, ctx, location);
629
                    }
630

M
Matthew Jasper 已提交
631 632 633 634 635 636 637 638 639 640 641 642
                    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 已提交
643
                    Rvalue::Len(path) => {
644 645 646 647 648
                        self.visit_place(
                            path,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
649
                    }
650

M
Matthew Jasper 已提交
651
                    Rvalue::Cast(_cast_kind, operand, ty) => {
652
                        self.visit_operand(operand, location);
653
                        self.visit_ty(ty, TyContext::Location(location));
654
                    }
655

M
Matthew Jasper 已提交
656 657
                    Rvalue::BinaryOp(_bin_op, lhs, rhs)
                    | Rvalue::CheckedBinaryOp(_bin_op, lhs, rhs) => {
658 659
                        self.visit_operand(lhs, location);
                        self.visit_operand(rhs, location);
660
                    }
661

M
Matthew Jasper 已提交
662
                    Rvalue::UnaryOp(_un_op, op) => {
663
                        self.visit_operand(op, location);
664
                    }
665

M
Matthew Jasper 已提交
666
                    Rvalue::Discriminant(place) => {
667 668 669 670 671
                        self.visit_place(
                            place,
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                            location
                        );
672 673
                    }

M
Matthew Jasper 已提交
674
                    Rvalue::NullaryOp(_op, ty) => {
675
                        self.visit_ty(ty, TyContext::Location(location));
676
                    }
677

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

N
Niko Matsakis 已提交
710
                        for operand in operands {
711
                            self.visit_operand(operand, location);
712 713
                        }
                    }
714 715 716
                }
            }

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

741
            fn super_ascribe_user_ty(&mut self,
M
Matthew Jasper 已提交
742 743
                                     place: & $($mutability)? Place<'tcx>,
                                     _variance: & $($mutability)? ty::Variance,
744
                                     user_ty: & $($mutability)? UserTypeProjection,
745
                                     location: Location) {
746 747 748 749 750
                self.visit_place(
                    place,
                    PlaceContext::NonUse(NonUseContext::AscribeUserTy),
                    location
                );
751
                self.visit_user_type_projection(user_ty);
D
David Wood 已提交
752 753
            }

754 755 756 757 758
            fn super_coverage(&mut self,
                              _kind: & $($mutability)? Coverage,
                              _location: Location) {
            }

759
            fn super_retag(&mut self,
M
Matthew Jasper 已提交
760 761
                           _kind: & $($mutability)? RetagKind,
                           place: & $($mutability)? Place<'tcx>,
762 763 764 765 766 767 768 769
                           location: Location) {
                self.visit_place(
                    place,
                    PlaceContext::MutatingUse(MutatingUseContext::Retag),
                    location,
                );
            }

770
            fn super_local_decl(&mut self,
771
                                local: Local,
M
Matthew Jasper 已提交
772
                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
773
                let LocalDecl {
N
Niko Matsakis 已提交
774
                    mutability: _,
M
Matthew Jasper 已提交
775 776 777
                    ty,
                    user_ty,
                    source_info,
778
                    internal: _,
M
Matthew Jasper 已提交
779
                    local_info: _,
780
                    is_block_tail: _,
M
Matthew Jasper 已提交
781
                } = local_decl;
N
Niko Matsakis 已提交
782

783 784
                self.visit_ty(ty, TyContext::LocalDecl {
                    local,
785
                    source_info: *source_info,
786
                });
787 788 789 790
                if let Some(user_ty) = user_ty {
                    for (user_ty, _) in & $($mutability)? user_ty.contents {
                        self.visit_user_type_projection(user_ty);
                    }
791
                }
792
                self.visit_source_info(source_info);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
            }

            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 已提交
810 811
            }

812
            fn super_source_scope(&mut self,
M
Matthew Jasper 已提交
813
                                      _scope: & $($mutability)? SourceScope) {
N
Niko Matsakis 已提交
814 815
            }

816
            fn super_constant(&mut self,
M
Matthew Jasper 已提交
817
                              constant: & $($mutability)? Constant<'tcx>,
818
                              location: Location) {
N
Niko Matsakis 已提交
819
                let Constant {
M
Matthew Jasper 已提交
820 821 822 823
                    span,
                    user_ty,
                    literal,
                } = constant;
N
Niko Matsakis 已提交
824 825

                self.visit_span(span);
826
                drop(user_ty); // no visit method for this
827
                self.visit_const(literal, location);
828 829
            }

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

M
Matthew Jasper 已提交
833
            fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
834
                let SourceInfo {
M
Matthew Jasper 已提交
835 836 837
                    span,
                    scope,
                } = source_info;
838 839

                self.visit_span(span);
840
                self.visit_source_scope(scope);
841 842
            }

843 844
            fn super_user_type_projection(
                &mut self,
845
                _ty: & $($mutability)? UserTypeProjection,
846 847 848
            ) {
            }

N
Niko Matsakis 已提交
849 850
            fn super_user_type_annotation(
                &mut self,
D
David Wood 已提交
851
                _index: UserTypeAnnotationIndex,
M
Matthew Jasper 已提交
852
                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
N
Niko Matsakis 已提交
853
            ) {
M
Matthew Jasper 已提交
854 855
                self.visit_span(& $($mutability)? ty.span);
                self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
856 857
            }

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

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

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

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

870
            // Convenience methods
871

872 873
            fn visit_location(
                &mut self,
D
Dylan MacKenzie 已提交
874
                body: &$($mutability)? Body<'tcx>,
875 876
                location: Location
            ) {
D
Dylan MacKenzie 已提交
877 878 879 880 881
                macro_rules! basic_blocks {
                    (mut) => (body.basic_blocks_mut());
                    () => (body.basic_blocks());
                };
                let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
882 883 884 885 886 887 888 889
                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)
890 891
                }
            }
892 893
        }
    }
894
}
895

896
macro_rules! visit_place_fns {
897
    (mut) => {
S
Santiago Pastorino 已提交
898 899
        fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;

900 901
        fn super_place(
            &mut self,
902 903 904
            place: &mut Place<'tcx>,
            context: PlaceContext,
            location: Location,
905
        ) {
906
            self.visit_local(&mut place.local, context, location);
907

908
            if let Some(new_projection) = self.process_projection(&place.projection, location) {
S
Santiago Pastorino 已提交
909
                place.projection = self.tcx().intern_place_elems(&new_projection);
910
            }
911 912 913 914
        }

        fn process_projection(
            &mut self,
915
            projection: &'a [PlaceElem<'tcx>],
916
            location: Location,
S
Santiago Pastorino 已提交
917
        ) -> Option<Vec<PlaceElem<'tcx>>> {
918
            let mut projection = Cow::Borrowed(projection);
919

920
            for i in 0..projection.len() {
B
Bastian Kauschke 已提交
921
                if let Some(&elem) = projection.get(i) {
922
                    if let Some(elem) = self.process_projection_elem(elem, location) {
S
Santiago Pastorino 已提交
923 924
                        // This converts the borrowed projection into `Cow::Owned(_)` and returns a
                        // clone of the projection so we can mutate and reintern later.
925 926 927 928 929 930 931 932
                        let vec = projection.to_mut();
                        vec[i] = elem;
                    }
                }
            }

            match projection {
                Cow::Borrowed(_) => None,
S
Santiago Pastorino 已提交
933
                Cow::Owned(vec) => Some(vec),
934
            }
935 936 937 938
        }

        fn process_projection_elem(
            &mut self,
B
Bastian Kauschke 已提交
939
            elem: PlaceElem<'tcx>,
940
            location: Location,
941
        ) -> Option<PlaceElem<'tcx>> {
942 943
            match elem {
                PlaceElem::Index(local) => {
B
Bastian Kauschke 已提交
944
                    let mut new_local = local;
945 946 947 948 949 950
                    self.visit_local(
                        &mut new_local,
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                        location,
                    );

B
Bastian Kauschke 已提交
951
                    if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
952 953 954 955 956 957 958
                }
                PlaceElem::Deref
                | PlaceElem::Field(..)
                | PlaceElem::ConstantIndex { .. }
                | PlaceElem::Subslice { .. }
                | PlaceElem::Downcast(..) => None,
            }
959
        }
960
    };
961

962
    () => {
963 964
        fn visit_projection(
            &mut self,
965
            local: Local,
966 967 968 969
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
970
            self.super_projection(local, projection, context, location);
971 972 973 974
        }

        fn visit_projection_elem(
            &mut self,
975
            local: Local,
976
            proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
977
            elem: PlaceElem<'tcx>,
978 979 980
            context: PlaceContext,
            location: Location,
        ) {
981
            self.super_projection_elem(local, proj_base, elem, context, location);
982 983
        }

984
        fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
985 986 987 988 989 990 991 992 993 994
            let mut context = context;

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

995
            self.visit_local(&place.local, context, location);
996

997
            self.visit_projection(place.local, &place.projection, context, location);
998 999 1000 1001
        }

        fn super_projection(
            &mut self,
1002
            local: Local,
1003 1004 1005 1006 1007
            projection: &[PlaceElem<'tcx>],
            context: PlaceContext,
            location: Location,
        ) {
            let mut cursor = projection;
B
Bastian Kauschke 已提交
1008
            while let &[ref proj_base @ .., elem] = cursor {
1009
                cursor = proj_base;
1010
                self.visit_projection_elem(local, cursor, elem, context, location);
1011 1012 1013 1014 1015
            }
        }

        fn super_projection_elem(
            &mut self,
1016
            _local: Local,
1017
            _proj_base: &[PlaceElem<'tcx>],
B
Bastian Kauschke 已提交
1018
            elem: PlaceElem<'tcx>,
1019 1020 1021 1022 1023 1024 1025 1026 1027
            _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 已提交
1028
                        &local,
1029
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1030
                        location,
1031 1032
                    );
                }
1033 1034 1035 1036
                ProjectionElem::Deref
                | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
                | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
                | ProjectionElem::Downcast(_, _) => {}
1037 1038
            }
        }
1039
    };
1040 1041
}

1042
make_mir_visitor!(Visitor,);
M
Mark Rousskov 已提交
1043
make_mir_visitor!(MutVisitor, mut);
1044

S
Santiago Pastorino 已提交
1045 1046 1047 1048 1049
pub trait MirVisitable<'tcx> {
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
}

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

impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
M
Mark Rousskov 已提交
1056
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1057
        visitor.visit_terminator(self, location)
S
Santiago Pastorino 已提交
1058 1059 1060 1061
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
M
Mark Rousskov 已提交
1062
    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
1063
        visitor.visit_terminator(self.as_ref().unwrap(), location)
S
Santiago Pastorino 已提交
1064 1065 1066
    }
}

1067 1068
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
1069
#[derive(Debug)]
1070 1071 1072 1073 1074 1075 1076 1077 1078
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,
    },

1079 1080 1081
    /// The inferred type of a user type annotation.
    UserTy(Span),

N
Niko Matsakis 已提交
1082 1083
    /// The return type of the function.
    ReturnTy(SourceInfo),
1084

1085 1086
    YieldTy(SourceInfo),

N
Niko Matsakis 已提交
1087 1088
    /// A type found at some location.
    Location(Location),
1089 1090
}

1091
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1092
pub enum NonMutatingUseContext {
1093 1094 1095 1096 1097 1098 1099
    /// 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.
1100
    SharedBorrow,
1101
    /// Shallow borrow.
1102
    ShallowBorrow,
1103
    /// Unique borrow.
1104
    UniqueBorrow,
M
Matthew Jasper 已提交
1105 1106
    /// AddressOf for *const pointer.
    AddressOf,
1107
    /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1108 1109 1110 1111 1112 1113 1114
    /// For example, the projection `x.y` is not marked as a mutation in these cases:
    ///
    ///     z = x.y;
    ///     f(&x.y);
    ///
    Projection,
}
1115

1116
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1117
pub enum MutatingUseContext {
1118 1119 1120 1121 1122
    /// 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.
1123
    AsmOutput,
1124
    /// Destination of a call.
1125
    Call,
1126 1127
    /// Destination of a yield.
    Yield,
1128
    /// Being dropped.
1129
    Drop,
1130
    /// Mutable borrow.
1131
    Borrow,
M
Matthew Jasper 已提交
1132 1133
    /// AddressOf for *mut pointer.
    AddressOf,
1134
    /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1135 1136 1137 1138 1139 1140
    /// For example, the projection `x.y` is marked as a mutation in these cases:
    ///
    ///     x.y = ...;
    ///     f(&mut x.y);
    ///
    Projection,
1141
    /// Retagging, a "Stacked Borrows" shadow state operation
1142
    Retag,
1143
}
1144

1145 1146 1147
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum NonUseContext {
    /// Starting a storage live range.
1148
    StorageLive,
1149
    /// Ending a storage live range.
1150
    StorageDead,
1151 1152
    /// User type annotation assertions for NLL.
    AscribeUserTy,
1153 1154
    /// Coverage code region and counter metadata.
    Coverage,
1155 1156
    /// The data of an user variable, for debug info.
    VarDebugInfo,
1157
}
1158

1159
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1160 1161 1162
pub enum PlaceContext {
    NonMutatingUse(NonMutatingUseContext),
    MutatingUse(MutatingUseContext),
1163 1164 1165
    NonUse(NonUseContext),
}

1166
impl PlaceContext {
1167
    /// Returns `true` if this place context represents a drop.
1168 1169
    pub fn is_drop(&self) -> bool {
        match *self {
1170 1171 1172 1173 1174 1175 1176 1177
            PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
            _ => false,
        }
    }

    /// Returns `true` if this place context represents a borrow.
    pub fn is_borrow(&self) -> bool {
        match *self {
1178 1179 1180 1181 1182
            PlaceContext::NonMutatingUse(
                NonMutatingUseContext::SharedBorrow
                | NonMutatingUseContext::ShallowBorrow
                | NonMutatingUseContext::UniqueBorrow,
            )
M
Mark Rousskov 已提交
1183
            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
1184 1185 1186 1187
            _ => false,
        }
    }

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

1196
    /// Returns `true` if this place context represents a storage live marker.
1197 1198
    pub fn is_storage_live_marker(&self) -> bool {
        match *self {
1199
            PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1200 1201 1202 1203
            _ => false,
        }
    }

1204
    /// Returns `true` if this place context represents a storage dead marker.
1205 1206
    pub fn is_storage_dead_marker(&self) -> bool {
        match *self {
1207
            PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1208 1209 1210 1211
            _ => false,
        }
    }

1212
    /// Returns `true` if this place context represents a use that potentially changes the value.
1213 1214
    pub fn is_mutating_use(&self) -> bool {
        match *self {
1215 1216
            PlaceContext::MutatingUse(..) => true,
            _ => false,
1217 1218 1219
        }
    }

1220
    /// Returns `true` if this place context represents a use that does not change the value.
1221 1222
    pub fn is_nonmutating_use(&self) -> bool {
        match *self {
1223 1224
            PlaceContext::NonMutatingUse(..) => true,
            _ => false,
1225 1226 1227
        }
    }

1228
    /// Returns `true` if this place context represents a use.
1229
    pub fn is_use(&self) -> bool {
1230 1231 1232 1233 1234 1235 1236 1237 1238
        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 {
1239 1240 1241 1242 1243
            PlaceContext::MutatingUse(
                MutatingUseContext::Store
                | MutatingUseContext::Call
                | MutatingUseContext::AsmOutput,
            ) => true,
1244 1245
            _ => false,
        }
1246 1247
    }
}