]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/mir/visit.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_middle / src / mir / visit.rs
CommitLineData
fc512014
XL
1//! # The MIR Visitor
2//!
3//! ## Overview
4//!
5//! There are two visitors, one for immutable and one for mutable references,
9c376795
FG
6//! but both are generated by the `make_mir_visitor` macro.
7//! The code is written according to the following conventions:
fc512014
XL
8//!
9//! - introduce a `visit_foo` and a `super_foo` method for every MIR type
10//! - `visit_foo`, by default, calls `super_foo`
11//! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
12//!
9c376795
FG
13//! This allows you to override `visit_foo` for types you are
14//! interested in, and invoke (within that method call)
fc512014
XL
15//! `self.super_foo` to get the default behavior. Just as in an OO
16//! language, you should never call `super` methods ordinarily except
17//! in that circumstance.
18//!
19//! For the most part, we do not destructure things external to the
20//! MIR, e.g., types, spans, etc, but simply visit them and stop. This
21//! avoids duplication with other visitors like `TypeFoldable`.
22//!
23//! ## Updating
24//!
25//! The code is written in a very deliberate style intended to minimize
26//! the chance of things being overlooked. You'll notice that we always
27//! use pattern matching to reference fields and we ensure that all
28//! matches are exhaustive.
29//!
30//! For example, the `super_basic_block_data` method begins like this:
31//!
04454e1e 32//! ```ignore (pseudo-rust)
064997fb
FG
33//! fn super_basic_block_data(
34//! &mut self,
35//! block: BasicBlock,
36//! data: & $($mutability)? BasicBlockData<'tcx>
37//! ) {
fc512014
XL
38//! let BasicBlockData {
39//! statements,
40//! terminator,
41//! is_cleanup: _
42//! } = *data;
43//!
44//! for statement in statements {
45//! self.visit_statement(block, statement);
46//! }
47//!
48//! ...
49//! }
50//! ```
51//!
52//! Here we used `let BasicBlockData { <fields> } = *data` deliberately,
53//! rather than writing `data.statements` in the body. This is because if one
54//! adds a new field to `BasicBlockData`, one will be forced to revise this code,
55//! and hence one will (hopefully) invoke the correct visit methods (if any).
56//!
57//! For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
58//! That means you never write `..` to skip over fields, nor do you write `_`
59//! to skip over variants in a `match`.
60//!
61//! The only place that `_` is acceptable is to match a field (or
62//! variant argument) that does not require visiting, as in
63//! `is_cleanup` above.
64
dfeec247 65use crate::mir::*;
532ac7d7 66use crate::ty::subst::SubstsRef;
e74abb32 67use crate::ty::{CanonicalUserTypeAnnotation, Ty};
dfeec247 68use rustc_span::Span;
92a42be0 69
9cc50fc6 70macro_rules! make_mir_visitor {
9fa01778 71 ($visitor_trait_name:ident, $($mutability:ident)?) => {
9cc50fc6
SL
72 pub trait $visitor_trait_name<'tcx> {
73 // Override these, and call `self.super_xxx` to revert back to the
74 // default behavior.
92a42be0 75
60c5eb7d
XL
76 fn visit_body(
77 &mut self,
f9f354fc 78 body: &$($mutability)? Body<'tcx>,
60c5eb7d 79 ) {
dc9dc135 80 self.super_body(body);
9cc50fc6 81 }
92a42be0 82
f2b60f7d
FG
83 extra_body_methods!($($mutability)?);
84
064997fb
FG
85 fn visit_basic_block_data(
86 &mut self,
87 block: BasicBlock,
88 data: & $($mutability)? BasicBlockData<'tcx>,
89 ) {
9cc50fc6
SL
90 self.super_basic_block_data(block, data);
91 }
92a42be0 92
064997fb
FG
93 fn visit_source_scope_data(
94 &mut self,
95 scope_data: & $($mutability)? SourceScopeData<'tcx>,
96 ) {
94b46f34 97 self.super_source_scope_data(scope_data);
54a0048b
SL
98 }
99
064997fb
FG
100 fn visit_statement(
101 &mut self,
102 statement: & $($mutability)? Statement<'tcx>,
103 location: Location,
104 ) {
48663c56 105 self.super_statement(statement, location);
92a42be0 106 }
9cc50fc6 107
064997fb
FG
108 fn visit_assign(
109 &mut self,
110 place: & $($mutability)? Place<'tcx>,
111 rvalue: & $($mutability)? Rvalue<'tcx>,
112 location: Location,
113 ) {
48663c56 114 self.super_assign(place, rvalue, location);
92a42be0 115 }
92a42be0 116
064997fb
FG
117 fn visit_terminator(
118 &mut self,
119 terminator: & $($mutability)? Terminator<'tcx>,
120 location: Location,
121 ) {
48663c56 122 self.super_terminator(terminator, location);
9cc50fc6 123 }
92a42be0 124
064997fb
FG
125 fn visit_assert_message(
126 &mut self,
127 msg: & $($mutability)? AssertMessage<'tcx>,
128 location: Location,
129 ) {
9e0c209e 130 self.super_assert_message(msg, location);
3157f602
XL
131 }
132
064997fb
FG
133 fn visit_rvalue(
134 &mut self,
135 rvalue: & $($mutability)? Rvalue<'tcx>,
136 location: Location,
137 ) {
9e0c209e 138 self.super_rvalue(rvalue, location);
92a42be0
SL
139 }
140
064997fb
FG
141 fn visit_operand(
142 &mut self,
143 operand: & $($mutability)? Operand<'tcx>,
144 location: Location,
145 ) {
9e0c209e 146 self.super_operand(operand, location);
92a42be0
SL
147 }
148
064997fb
FG
149 fn visit_ascribe_user_ty(
150 &mut self,
151 place: & $($mutability)? Place<'tcx>,
152 variance: $(& $mutability)? ty::Variance,
153 user_ty: & $($mutability)? UserTypeProjection,
154 location: Location,
155 ) {
0bf4aa26 156 self.super_ascribe_user_ty(place, variance, user_ty, location);
0531ce1d
XL
157 }
158
064997fb
FG
159 fn visit_coverage(
160 &mut self,
161 coverage: & $($mutability)? Coverage,
162 location: Location,
163 ) {
3dfed10e
XL
164 self.super_coverage(coverage, location);
165 }
166
064997fb
FG
167 fn visit_retag(
168 &mut self,
169 kind: $(& $mutability)? RetagKind,
170 place: & $($mutability)? Place<'tcx>,
171 location: Location,
172 ) {
0731742a 173 self.super_retag(kind, place, location);
a1dfa0c6
XL
174 }
175
064997fb
FG
176 fn visit_place(
177 &mut self,
178 place: & $($mutability)? Place<'tcx>,
179 context: PlaceContext,
180 location: Location,
181 ) {
ff7c6d11 182 self.super_place(place, context, location);
92a42be0
SL
183 }
184
e74abb32 185 visit_place_fns!($($mutability)?);
54a0048b 186
064997fb
FG
187 fn visit_constant(
188 &mut self,
189 constant: & $($mutability)? Constant<'tcx>,
190 location: Location,
191 ) {
9e0c209e 192 self.super_constant(constant, location);
92a42be0
SL
193 }
194
064997fb
FG
195 fn visit_span(
196 &mut self,
197 span: $(& $mutability)? Span,
198 ) {
9cc50fc6 199 self.super_span(span);
92a42be0
SL
200 }
201
064997fb
FG
202 fn visit_source_info(
203 &mut self,
204 source_info: & $($mutability)? SourceInfo,
205 ) {
3157f602
XL
206 self.super_source_info(source_info);
207 }
208
064997fb
FG
209 fn visit_ty(
210 &mut self,
211 ty: $(& $mutability)? Ty<'tcx>,
212 _: TyContext,
213 ) {
54a0048b
SL
214 self.super_ty(ty);
215 }
216
0bf4aa26
XL
217 fn visit_user_type_projection(
218 &mut self,
532ac7d7 219 ty: & $($mutability)? UserTypeProjection,
0bf4aa26
XL
220 ) {
221 self.super_user_type_projection(ty);
222 }
223
224 fn visit_user_type_annotation(
225 &mut self,
0731742a 226 index: UserTypeAnnotationIndex,
9fa01778 227 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
0bf4aa26 228 ) {
0731742a 229 self.super_user_type_annotation(index, ty);
b7449926
XL
230 }
231
064997fb
FG
232 fn visit_region(
233 &mut self,
234 region: $(& $mutability)? ty::Region<'tcx>,
235 _: Location,
236 ) {
ea8adc8c
XL
237 self.super_region(region);
238 }
239
064997fb
FG
240 fn visit_substs(
241 &mut self,
242 substs: & $($mutability)? SubstsRef<'tcx>,
243 _: Location,
244 ) {
54a0048b
SL
245 self.super_substs(substs);
246 }
247
064997fb
FG
248 fn visit_local_decl(
249 &mut self,
250 local: Local,
251 local_decl: & $($mutability)? LocalDecl<'tcx>,
252 ) {
abe05a73 253 self.super_local_decl(local, local_decl);
54a0048b
SL
254 }
255
064997fb
FG
256 fn visit_var_debug_info(
257 &mut self,
258 var_debug_info: & $($mutability)* VarDebugInfo<'tcx>,
259 ) {
60c5eb7d
XL
260 self.super_var_debug_info(var_debug_info);
261 }
262
064997fb
FG
263 fn visit_local(
264 &mut self,
265 _local: $(& $mutability)? Local,
266 _context: PlaceContext,
267 _location: Location,
268 ) {}
ea8adc8c 269
064997fb
FG
270 fn visit_source_scope(
271 &mut self,
272 scope: $(& $mutability)? SourceScope,
273 ) {
94b46f34 274 self.super_source_scope(scope);
54a0048b
SL
275 }
276
9cc50fc6 277 // The `super_xxx` methods comprise the default behavior and are
7453a54e 278 // not meant to be overridden.
9cc50fc6 279
60c5eb7d
XL
280 fn super_body(
281 &mut self,
f9f354fc 282 body: &$($mutability)? Body<'tcx>,
60c5eb7d 283 ) {
f2b60f7d 284 super_body!(self, body, $($mutability, true)?);
92a42be0
SL
285 }
286
9cc50fc6
SL
287 fn super_basic_block_data(&mut self,
288 block: BasicBlock,
9fa01778 289 data: & $($mutability)? BasicBlockData<'tcx>) {
54a0048b 290 let BasicBlockData {
9fa01778
XL
291 statements,
292 terminator,
54a0048b 293 is_cleanup: _
9fa01778 294 } = data;
54a0048b 295
9e0c209e 296 let mut index = 0;
54a0048b 297 for statement in statements {
5869c6ff 298 let location = Location { block, statement_index: index };
48663c56 299 self.visit_statement(statement, location);
9e0c209e 300 index += 1;
9cc50fc6
SL
301 }
302
9fa01778 303 if let Some(terminator) = terminator {
5869c6ff 304 let location = Location { block, statement_index: index };
48663c56 305 self.visit_terminator(terminator, location);
9cc50fc6 306 }
92a42be0
SL
307 }
308
29967ef6
XL
309 fn super_source_scope_data(
310 &mut self,
311 scope_data: & $($mutability)? SourceScopeData<'tcx>,
312 ) {
94b46f34 313 let SourceScopeData {
9fa01778
XL
314 span,
315 parent_scope,
29967ef6
XL
316 inlined,
317 inlined_parent_scope,
60c5eb7d 318 local_data: _,
9fa01778 319 } = scope_data;
54a0048b 320
064997fb 321 self.visit_span($(& $mutability)? *span);
9fa01778 322 if let Some(parent_scope) = parent_scope {
064997fb 323 self.visit_source_scope($(& $mutability)? *parent_scope);
54a0048b 324 }
29967ef6
XL
325 if let Some((callee, callsite_span)) = inlined {
326 let location = START_BLOCK.start_location();
327
064997fb 328 self.visit_span($(& $mutability)? *callsite_span);
29967ef6
XL
329
330 let ty::Instance { def: callee_def, substs: callee_substs } = callee;
331 match callee_def {
332 ty::InstanceDef::Item(_def_id) => {}
333
334 ty::InstanceDef::Intrinsic(_def_id) |
064997fb 335 ty::InstanceDef::VTableShim(_def_id) |
29967ef6
XL
336 ty::InstanceDef::ReifyShim(_def_id) |
337 ty::InstanceDef::Virtual(_def_id, _) |
c295e0f8 338 ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
29967ef6
XL
339 ty::InstanceDef::DropGlue(_def_id, None) => {}
340
341 ty::InstanceDef::FnPtrShim(_def_id, ty) |
342 ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
343 ty::InstanceDef::CloneShim(_def_id, ty) => {
344 // FIXME(eddyb) use a better `TyContext` here.
5099ac24 345 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
29967ef6
XL
346 }
347 }
348 self.visit_substs(callee_substs, location);
349 }
350 if let Some(inlined_parent_scope) = inlined_parent_scope {
064997fb 351 self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
29967ef6 352 }
54a0048b
SL
353 }
354
9cc50fc6 355 fn super_statement(&mut self,
9fa01778 356 statement: & $($mutability)? Statement<'tcx>,
9e0c209e 357 location: Location) {
54a0048b 358 let Statement {
9fa01778
XL
359 source_info,
360 kind,
361 } = statement;
54a0048b 362
3157f602 363 self.visit_source_info(source_info);
9fa01778 364 match kind {
e1599b0c 365 StatementKind::Assign(
064997fb 366 box (place, rvalue)
e1599b0c 367 ) => {
48663c56 368 self.visit_assign(place, rvalue, location);
9cc50fc6 369 }
cdc7bbd5 370 StatementKind::FakeRead(box (_, place)) => {
13cf67c4
XL
371 self.visit_place(
372 place,
373 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
374 location
375 );
94b46f34 376 }
9fa01778 377 StatementKind::SetDiscriminant { place, .. } => {
13cf67c4
XL
378 self.visit_place(
379 place,
04454e1e 380 PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
13cf67c4
XL
381 location
382 );
5bcae85e 383 }
04454e1e
FG
384 StatementKind::Deinit(place) => {
385 self.visit_place(
386 place,
387 PlaceContext::MutatingUse(MutatingUseContext::Deinit),
388 location
389 )
390 }
9fa01778 391 StatementKind::StorageLive(local) => {
13cf67c4 392 self.visit_local(
064997fb 393 $(& $mutability)? *local,
13cf67c4
XL
394 PlaceContext::NonUse(NonUseContext::StorageLive),
395 location
396 );
5bcae85e 397 }
9fa01778 398 StatementKind::StorageDead(local) => {
13cf67c4 399 self.visit_local(
064997fb 400 $(& $mutability)? *local,
13cf67c4
XL
401 PlaceContext::NonUse(NonUseContext::StorageDead),
402 location
403 );
5bcae85e 404 }
9fa01778 405 StatementKind::Retag(kind, place) => {
064997fb 406 self.visit_retag($(& $mutability)? *kind, place, location);
a1dfa0c6 407 }
e1599b0c 408 StatementKind::AscribeUserType(
064997fb 409 box (place, user_ty),
e1599b0c
XL
410 variance
411 ) => {
064997fb 412 self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location);
0531ce1d 413 }
3dfed10e
XL
414 StatementKind::Coverage(coverage) => {
415 self.visit_coverage(
416 coverage,
417 location
418 )
419 }
f2b60f7d
FG
420 StatementKind::Intrinsic(box ref $($mutability)? intrinsic) => {
421 match intrinsic {
422 NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
423 NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
424 self.visit_operand(src, location);
425 self.visit_operand(dst, location);
426 self.visit_operand(count, location);
427 }
428 }
6a06907d 429 }
9e0c209e 430 StatementKind::Nop => {}
9cc50fc6 431 }
92a42be0
SL
432 }
433
9cc50fc6 434 fn super_assign(&mut self,
9fa01778
XL
435 place: &$($mutability)? Place<'tcx>,
436 rvalue: &$($mutability)? Rvalue<'tcx>,
9e0c209e 437 location: Location) {
13cf67c4
XL
438 self.visit_place(
439 place,
440 PlaceContext::MutatingUse(MutatingUseContext::Store),
441 location
442 );
9e0c209e 443 self.visit_rvalue(rvalue, location);
92a42be0
SL
444 }
445
9cc50fc6 446 fn super_terminator(&mut self,
9fa01778 447 terminator: &$($mutability)? Terminator<'tcx>,
9e0c209e 448 location: Location) {
9fa01778 449 let Terminator { source_info, kind } = terminator;
54a0048b 450
3157f602 451 self.visit_source_info(source_info);
9fa01778 452 match kind {
48663c56
XL
453 TerminatorKind::Goto { .. } |
454 TerminatorKind::Resume |
455 TerminatorKind::Abort |
48663c56
XL
456 TerminatorKind::GeneratorDrop |
457 TerminatorKind::Unreachable |
f035d41b 458 TerminatorKind::FalseEdge { .. } |
064997fb 459 TerminatorKind::FalseUnwind { .. } => {}
9cc50fc6 460
f9f354fc
XL
461 TerminatorKind::Return => {
462 // `return` logically moves from the return place `_0`. Note that the place
463 // cannot be changed by any visitor, though.
464 let $($mutability)? local = RETURN_PLACE;
465 self.visit_local(
064997fb 466 $(& $mutability)? local,
f9f354fc 467 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
f035d41b 468 location,
f9f354fc
XL
469 );
470
471 assert_eq!(
472 local,
473 RETURN_PLACE,
474 "`MutVisitor` tried to mutate return place of `return` terminator"
475 );
476 }
477
9fa01778
XL
478 TerminatorKind::SwitchInt {
479 discr,
48663c56 480 targets: _
9fa01778 481 } => {
f035d41b 482 self.visit_operand(discr, location);
9cc50fc6
SL
483 }
484
9fa01778 485 TerminatorKind::Drop {
f035d41b 486 place,
48663c56
XL
487 target: _,
488 unwind: _,
9fa01778 489 } => {
13cf67c4 490 self.visit_place(
f035d41b 491 place,
13cf67c4 492 PlaceContext::MutatingUse(MutatingUseContext::Drop),
f035d41b 493 location
13cf67c4 494 );
3157f602
XL
495 }
496
9fa01778 497 TerminatorKind::DropAndReplace {
f035d41b 498 place,
9fa01778 499 value,
48663c56
XL
500 target: _,
501 unwind: _,
9fa01778 502 } => {
13cf67c4 503 self.visit_place(
f035d41b 504 place,
13cf67c4 505 PlaceContext::MutatingUse(MutatingUseContext::Drop),
f035d41b 506 location
13cf67c4 507 );
f035d41b 508 self.visit_operand(value, location);
7453a54e
SL
509 }
510
9fa01778
XL
511 TerminatorKind::Call {
512 func,
513 args,
514 destination,
923072b8 515 target: _,
48663c56 516 cleanup: _,
9fa01778 517 from_hir_call: _,
f035d41b 518 fn_span: _
9fa01778 519 } => {
f035d41b 520 self.visit_operand(func, location);
9cc50fc6 521 for arg in args {
f035d41b 522 self.visit_operand(arg, location);
9cc50fc6 523 }
923072b8
FG
524 self.visit_place(
525 destination,
526 PlaceContext::MutatingUse(MutatingUseContext::Call),
527 location
528 );
9cc50fc6 529 }
3157f602 530
9fa01778
XL
531 TerminatorKind::Assert {
532 cond,
533 expected: _,
534 msg,
48663c56
XL
535 target: _,
536 cleanup: _,
9fa01778 537 } => {
f035d41b
XL
538 self.visit_operand(cond, location);
539 self.visit_assert_message(msg, location);
3157f602 540 }
ea8adc8c 541
9fa01778
XL
542 TerminatorKind::Yield {
543 value,
48663c56 544 resume: _,
74b04a01 545 resume_arg,
48663c56 546 drop: _,
9fa01778 547 } => {
f035d41b 548 self.visit_operand(value, location);
74b04a01
XL
549 self.visit_place(
550 resume_arg,
f9f354fc 551 PlaceContext::MutatingUse(MutatingUseContext::Yield),
f035d41b 552 location,
74b04a01 553 );
ea8adc8c
XL
554 }
555
f9f354fc
XL
556 TerminatorKind::InlineAsm {
557 template: _,
558 operands,
559 options: _,
560 line_spans: _,
561 destination: _,
a2a8927a 562 cleanup: _,
f9f354fc
XL
563 } => {
564 for op in operands {
565 match op {
cdc7bbd5 566 InlineAsmOperand::In { value, .. } => {
f035d41b 567 self.visit_operand(value, location);
f9f354fc 568 }
94222f64
XL
569 InlineAsmOperand::Out { place: Some(place), .. } => {
570 self.visit_place(
571 place,
a2a8927a 572 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
94222f64
XL
573 location,
574 );
f9f354fc
XL
575 }
576 InlineAsmOperand::InOut { in_value, out_place, .. } => {
f035d41b 577 self.visit_operand(in_value, location);
f9f354fc
XL
578 if let Some(out_place) = out_place {
579 self.visit_place(
580 out_place,
a2a8927a 581 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
f035d41b 582 location,
f9f354fc
XL
583 );
584 }
585 }
cdc7bbd5
XL
586 InlineAsmOperand::Const { value }
587 | InlineAsmOperand::SymFn { value } => {
f035d41b 588 self.visit_constant(value, location);
f9f354fc 589 }
94222f64
XL
590 InlineAsmOperand::Out { place: None, .. }
591 | InlineAsmOperand::SymStatic { def_id: _ } => {}
f9f354fc
XL
592 }
593 }
594 }
3157f602
XL
595 }
596 }
597
598 fn super_assert_message(&mut self,
9fa01778 599 msg: & $($mutability)? AssertMessage<'tcx>,
9e0c209e 600 location: Location) {
74b04a01 601 use crate::mir::AssertKind::*;
416331ca
XL
602 match msg {
603 BoundsCheck { len, index } => {
604 self.visit_operand(len, location);
605 self.visit_operand(index, location);
606 }
f035d41b
XL
607 Overflow(_, l, r) => {
608 self.visit_operand(l, location);
609 self.visit_operand(r, location);
610 }
611 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
612 self.visit_operand(op, location);
613 }
60c5eb7d 614 ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
416331ca
XL
615 // Nothing to visit
616 }
9cc50fc6 617 }
92a42be0
SL
618 }
619
9cc50fc6 620 fn super_rvalue(&mut self,
9fa01778 621 rvalue: & $($mutability)? Rvalue<'tcx>,
9e0c209e 622 location: Location) {
9fa01778
XL
623 match rvalue {
624 Rvalue::Use(operand) => {
9e0c209e 625 self.visit_operand(operand, location);
9cc50fc6
SL
626 }
627
9fa01778 628 Rvalue::Repeat(value, _) => {
9e0c209e 629 self.visit_operand(value, location);
9cc50fc6
SL
630 }
631
f9f354fc
XL
632 Rvalue::ThreadLocalRef(_) => {}
633
9fa01778 634 Rvalue::Ref(r, bk, path) => {
5099ac24 635 self.visit_region($(& $mutability)? *r, location);
13cf67c4
XL
636 let ctx = match bk {
637 BorrowKind::Shared => PlaceContext::NonMutatingUse(
48663c56 638 NonMutatingUseContext::SharedBorrow
13cf67c4
XL
639 ),
640 BorrowKind::Shallow => PlaceContext::NonMutatingUse(
48663c56 641 NonMutatingUseContext::ShallowBorrow
13cf67c4
XL
642 ),
643 BorrowKind::Unique => PlaceContext::NonMutatingUse(
48663c56 644 NonMutatingUseContext::UniqueBorrow
13cf67c4
XL
645 ),
646 BorrowKind::Mut { .. } =>
48663c56 647 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
13cf67c4
XL
648 };
649 self.visit_place(path, ctx, location);
9cc50fc6 650 }
064997fb
FG
651 Rvalue::CopyForDeref(place) => {
652 self.visit_place(
653 place,
654 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
655 location
656 );
657 }
9cc50fc6 658
dfeec247
XL
659 Rvalue::AddressOf(m, path) => {
660 let ctx = match m {
661 Mutability::Mut => PlaceContext::MutatingUse(
662 MutatingUseContext::AddressOf
663 ),
664 Mutability::Not => PlaceContext::NonMutatingUse(
665 NonMutatingUseContext::AddressOf
666 ),
667 };
668 self.visit_place(path, ctx, location);
669 }
670
9fa01778 671 Rvalue::Len(path) => {
13cf67c4
XL
672 self.visit_place(
673 path,
674 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
675 location
676 );
9cc50fc6
SL
677 }
678
9fa01778 679 Rvalue::Cast(_cast_kind, operand, ty) => {
9e0c209e 680 self.visit_operand(operand, location);
5099ac24 681 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
9cc50fc6
SL
682 }
683
6a06907d
XL
684 Rvalue::BinaryOp(_bin_op, box(lhs, rhs))
685 | Rvalue::CheckedBinaryOp(_bin_op, box(lhs, rhs)) => {
9e0c209e
SL
686 self.visit_operand(lhs, location);
687 self.visit_operand(rhs, location);
9cc50fc6
SL
688 }
689
9fa01778 690 Rvalue::UnaryOp(_un_op, op) => {
9e0c209e 691 self.visit_operand(op, location);
9cc50fc6
SL
692 }
693
9fa01778 694 Rvalue::Discriminant(place) => {
13cf67c4
XL
695 self.visit_place(
696 place,
697 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
698 location
699 );
8bb4bdeb
XL
700 }
701
9fa01778 702 Rvalue::NullaryOp(_op, ty) => {
5099ac24 703 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
9cc50fc6
SL
704 }
705
9fa01778
XL
706 Rvalue::Aggregate(kind, operands) => {
707 let kind = &$($mutability)? **kind;
708 match kind {
709 AggregateKind::Array(ty) => {
5099ac24 710 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
54a0048b
SL
711 }
712 AggregateKind::Tuple => {
713 }
9fa01778
XL
714 AggregateKind::Adt(
715 _adt_def,
716 _variant_index,
717 substs,
718 _user_substs,
719 _active_field_index
720 ) => {
3b2f2976 721 self.visit_substs(substs, location);
54a0048b 722 }
9fa01778 723 AggregateKind::Closure(
48663c56 724 _,
9fa01778
XL
725 closure_substs
726 ) => {
e74abb32 727 self.visit_substs(closure_substs, location);
9cc50fc6 728 }
9fa01778 729 AggregateKind::Generator(
48663c56 730 _,
9fa01778
XL
731 generator_substs,
732 _movability,
733 ) => {
e74abb32 734 self.visit_substs(generator_substs, location);
ea8adc8c 735 }
9cc50fc6
SL
736 }
737
54a0048b 738 for operand in operands {
9e0c209e 739 self.visit_operand(operand, location);
9cc50fc6
SL
740 }
741 }
c295e0f8
XL
742
743 Rvalue::ShallowInitBox(operand, ty) => {
744 self.visit_operand(operand, location);
5099ac24 745 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
c295e0f8 746 }
9cc50fc6 747 }
92a42be0
SL
748 }
749
9cc50fc6 750 fn super_operand(&mut self,
9fa01778 751 operand: & $($mutability)? Operand<'tcx>,
9e0c209e 752 location: Location) {
9fa01778
XL
753 match operand {
754 Operand::Copy(place) => {
13cf67c4
XL
755 self.visit_place(
756 place,
757 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
758 location
759 );
ff7c6d11 760 }
9fa01778 761 Operand::Move(place) => {
13cf67c4
XL
762 self.visit_place(
763 place,
764 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
765 location
766 );
9cc50fc6 767 }
9fa01778 768 Operand::Constant(constant) => {
9e0c209e 769 self.visit_constant(constant, location);
9cc50fc6 770 }
92a42be0
SL
771 }
772 }
773
b7449926 774 fn super_ascribe_user_ty(&mut self,
9fa01778 775 place: & $($mutability)? Place<'tcx>,
064997fb 776 _variance: $(& $mutability)? ty::Variance,
532ac7d7 777 user_ty: & $($mutability)? UserTypeProjection,
b7449926 778 location: Location) {
13cf67c4
XL
779 self.visit_place(
780 place,
781 PlaceContext::NonUse(NonUseContext::AscribeUserTy),
782 location
783 );
0bf4aa26 784 self.visit_user_type_projection(user_ty);
0531ce1d
XL
785 }
786
3dfed10e 787 fn super_coverage(&mut self,
29967ef6 788 _coverage: & $($mutability)? Coverage,
3dfed10e
XL
789 _location: Location) {
790 }
791
a1dfa0c6 792 fn super_retag(&mut self,
064997fb 793 _kind: $(& $mutability)? RetagKind,
9fa01778 794 place: & $($mutability)? Place<'tcx>,
a1dfa0c6
XL
795 location: Location) {
796 self.visit_place(
797 place,
798 PlaceContext::MutatingUse(MutatingUseContext::Retag),
799 location,
800 );
801 }
802
c30ab7b3 803 fn super_local_decl(&mut self,
abe05a73 804 local: Local,
9fa01778 805 local_decl: & $($mutability)? LocalDecl<'tcx>) {
c30ab7b3 806 let LocalDecl {
54a0048b 807 mutability: _,
9fa01778
XL
808 ty,
809 user_ty,
9fa01778 810 source_info,
ea8adc8c 811 internal: _,
60c5eb7d 812 local_info: _,
0bf4aa26 813 is_block_tail: _,
9fa01778 814 } = local_decl;
54a0048b 815
5099ac24 816 self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
abe05a73
XL
817 local,
818 source_info: *source_info,
819 });
f9f354fc
XL
820 if let Some(user_ty) = user_ty {
821 for (user_ty, _) in & $($mutability)? user_ty.contents {
822 self.visit_user_type_projection(user_ty);
823 }
b7449926 824 }
cc61c64b 825 self.visit_source_info(source_info);
60c5eb7d
XL
826 }
827
064997fb
FG
828 fn super_var_debug_info(
829 &mut self,
830 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
831 ) {
60c5eb7d
XL
832 let VarDebugInfo {
833 name: _,
834 source_info,
fc512014 835 value,
60c5eb7d
XL
836 } = var_debug_info;
837
838 self.visit_source_info(source_info);
839 let location = START_BLOCK.start_location();
fc512014
XL
840 match value {
841 VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
842 VarDebugInfoContents::Place(place) =>
843 self.visit_place(
844 place,
845 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
846 location
847 ),
487cf647
FG
848 VarDebugInfoContents::Composite { ty, fragments } => {
849 // FIXME(eddyb) use a better `TyContext` here.
850 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
851 for VarDebugInfoFragment { projection: _, contents } in fragments {
852 self.visit_place(
853 contents,
854 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
855 location,
856 );
857 }
858 }
fc512014 859 }
54a0048b
SL
860 }
861
064997fb
FG
862 fn super_source_scope(
863 &mut self,
864 _scope: $(& $mutability)? SourceScope
865 ) {}
54a0048b 866
064997fb
FG
867 fn super_constant(
868 &mut self,
869 constant: & $($mutability)? Constant<'tcx>,
870 location: Location
871 ) {
54a0048b 872 let Constant {
9fa01778 873 span,
9fa01778
XL
874 user_ty,
875 literal,
876 } = constant;
54a0048b 877
064997fb 878 self.visit_span($(& $mutability)? *span);
b7449926 879 drop(user_ty); // no visit method for this
6a06907d 880 match literal {
f2b60f7d 881 ConstantKind::Ty(_) => {}
5099ac24 882 ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
f2b60f7d 883 ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
6a06907d 884 }
92a42be0 885 }
92a42be0 886
064997fb 887 fn super_span(&mut self, _span: $(& $mutability)? Span) {
92a42be0 888 }
54a0048b 889
9fa01778 890 fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
3157f602 891 let SourceInfo {
9fa01778
XL
892 span,
893 scope,
894 } = source_info;
3157f602 895
064997fb
FG
896 self.visit_span($(& $mutability)? *span);
897 self.visit_source_scope($(& $mutability)? *scope);
3157f602
XL
898 }
899
0bf4aa26
XL
900 fn super_user_type_projection(
901 &mut self,
532ac7d7 902 _ty: & $($mutability)? UserTypeProjection,
0bf4aa26 903 ) {
0bf4aa26
XL
904 }
905
906 fn super_user_type_annotation(
907 &mut self,
0731742a 908 _index: UserTypeAnnotationIndex,
9fa01778 909 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
0bf4aa26 910 ) {
064997fb 911 self.visit_span($(& $mutability)? ty.span);
5099ac24 912 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
b7449926
XL
913 }
914
48663c56 915 fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
54a0048b
SL
916 }
917
5099ac24 918 fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
ea8adc8c
XL
919 }
920
532ac7d7 921 fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
54a0048b
SL
922 }
923
9e0c209e
SL
924 // Convenience methods
925
60c5eb7d
XL
926 fn visit_location(
927 &mut self,
f9f354fc 928 body: &$($mutability)? Body<'tcx>,
60c5eb7d
XL
929 location: Location
930 ) {
f2b60f7d 931 let basic_block = & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
9e0c209e 932 if basic_block.statements.len() == location.statement_index {
9fa01778 933 if let Some(ref $($mutability)? terminator) = basic_block.terminator {
48663c56 934 self.visit_terminator(terminator, location)
9e0c209e
SL
935 }
936 } else {
9fa01778 937 let statement = & $($mutability)?
9e0c209e 938 basic_block.statements[location.statement_index];
48663c56 939 self.visit_statement(statement, location)
9e0c209e
SL
940 }
941 }
92a42be0
SL
942 }
943 }
92a42be0
SL
944}
945
f2b60f7d
FG
946macro_rules! basic_blocks {
947 ($body:ident, mut, true) => {
948 $body.basic_blocks.as_mut()
949 };
950 ($body:ident, mut, false) => {
951 $body.basic_blocks.as_mut_preserves_cfg()
952 };
953 ($body:ident,) => {
954 $body.basic_blocks
955 };
956}
957
958macro_rules! basic_blocks_iter {
959 ($body:ident, mut, $invalidate:tt) => {
960 basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
961 };
962 ($body:ident,) => {
963 basic_blocks!($body,).iter_enumerated()
964 };
965}
966
967macro_rules! extra_body_methods {
968 (mut) => {
969 fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
970 self.super_body_preserves_cfg(body);
971 }
972
973 fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
974 super_body!(self, body, mut, false);
975 }
976 };
977 () => {};
978}
979
980macro_rules! super_body {
981 ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
982 let span = $body.span;
983 if let Some(gen) = &$($mutability)? $body.generator {
984 if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
985 $self.visit_ty(
986 yield_ty,
987 TyContext::YieldTy(SourceInfo::outermost(span))
988 );
989 }
990 }
991
992 for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
993 $self.visit_basic_block_data(bb, data);
994 }
995
996 for scope in &$($mutability)? $body.source_scopes {
997 $self.visit_source_scope_data(scope);
998 }
999
1000 $self.visit_ty(
1001 $(& $mutability)? $body.return_ty(),
1002 TyContext::ReturnTy(SourceInfo::outermost($body.span))
1003 );
1004
1005 for local in $body.local_decls.indices() {
1006 $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1007 }
1008
1009 #[allow(unused_macro_rules)]
1010 macro_rules! type_annotations {
1011 (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1012 () => ($body.user_type_annotations.iter_enumerated());
1013 }
1014
1015 for (index, annotation) in type_annotations!($($mutability)?) {
1016 $self.visit_user_type_annotation(
1017 index, annotation
1018 );
1019 }
1020
1021 for var_debug_info in &$($mutability)? $body.var_debug_info {
1022 $self.visit_var_debug_info(var_debug_info);
1023 }
1024
1025 $self.visit_span($(& $mutability)? $body.span);
1026
1027 for const_ in &$($mutability)? $body.required_consts {
1028 let location = START_BLOCK.start_location();
1029 $self.visit_constant(const_, location);
1030 }
1031 }
1032}
1033
e74abb32 1034macro_rules! visit_place_fns {
ba9703b0 1035 (mut) => {
e74abb32
XL
1036 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1037
1038 fn super_place(
1039 &mut self,
1040 place: &mut Place<'tcx>,
1041 context: PlaceContext,
1042 location: Location,
1043 ) {
f9f354fc 1044 self.visit_local(&mut place.local, context, location);
e74abb32 1045
ba9703b0 1046 if let Some(new_projection) = self.process_projection(&place.projection, location) {
e74abb32
XL
1047 place.projection = self.tcx().intern_place_elems(&new_projection);
1048 }
1049 }
1050
a2a8927a 1051 fn process_projection<'a>(
e74abb32
XL
1052 &mut self,
1053 projection: &'a [PlaceElem<'tcx>],
ba9703b0 1054 location: Location,
e74abb32
XL
1055 ) -> Option<Vec<PlaceElem<'tcx>>> {
1056 let mut projection = Cow::Borrowed(projection);
1057
1058 for i in 0..projection.len() {
f9f354fc 1059 if let Some(&elem) = projection.get(i) {
ba9703b0 1060 if let Some(elem) = self.process_projection_elem(elem, location) {
e74abb32
XL
1061 // This converts the borrowed projection into `Cow::Owned(_)` and returns a
1062 // clone of the projection so we can mutate and reintern later.
1063 let vec = projection.to_mut();
1064 vec[i] = elem;
1065 }
1066 }
1067 }
1068
1069 match projection {
1070 Cow::Borrowed(_) => None,
1071 Cow::Owned(vec) => Some(vec),
1072 }
1073 }
1074
1075 fn process_projection_elem(
1076 &mut self,
f9f354fc 1077 elem: PlaceElem<'tcx>,
ba9703b0 1078 location: Location,
e74abb32 1079 ) -> Option<PlaceElem<'tcx>> {
ba9703b0
XL
1080 match elem {
1081 PlaceElem::Index(local) => {
f9f354fc 1082 let mut new_local = local;
ba9703b0
XL
1083 self.visit_local(
1084 &mut new_local,
1085 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1086 location,
1087 );
1088
f9f354fc 1089 if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
ba9703b0 1090 }
a2a8927a
XL
1091 PlaceElem::Field(field, ty) => {
1092 let mut new_ty = ty;
1093 self.visit_ty(&mut new_ty, TyContext::Location(location));
1094 if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1095 }
2b03887a
FG
1096 PlaceElem::OpaqueCast(ty) => {
1097 let mut new_ty = ty;
1098 self.visit_ty(&mut new_ty, TyContext::Location(location));
1099 if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1100 }
ba9703b0 1101 PlaceElem::Deref
ba9703b0
XL
1102 | PlaceElem::ConstantIndex { .. }
1103 | PlaceElem::Subslice { .. }
1104 | PlaceElem::Downcast(..) => None,
1105 }
e74abb32 1106 }
ba9703b0 1107 };
e74abb32 1108
ba9703b0 1109 () => {
e74abb32
XL
1110 fn visit_projection(
1111 &mut self,
6a06907d 1112 place_ref: PlaceRef<'tcx>,
e74abb32
XL
1113 context: PlaceContext,
1114 location: Location,
1115 ) {
6a06907d 1116 self.super_projection(place_ref, context, location);
e74abb32
XL
1117 }
1118
1119 fn visit_projection_elem(
1120 &mut self,
74b04a01 1121 local: Local,
e74abb32 1122 proj_base: &[PlaceElem<'tcx>],
f9f354fc 1123 elem: PlaceElem<'tcx>,
e74abb32
XL
1124 context: PlaceContext,
1125 location: Location,
1126 ) {
dfeec247 1127 self.super_projection_elem(local, proj_base, elem, context, location);
e74abb32
XL
1128 }
1129
ba9703b0 1130 fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
e74abb32
XL
1131 let mut context = context;
1132
1133 if !place.projection.is_empty() {
fc512014
XL
1134 if context.is_use() {
1135 // ^ Only change the context if it is a real use, not a "use" in debuginfo.
1136 context = if context.is_mutating_use() {
1137 PlaceContext::MutatingUse(MutatingUseContext::Projection)
1138 } else {
1139 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
1140 };
1141 }
e74abb32
XL
1142 }
1143
064997fb 1144 self.visit_local(place.local, context, location);
e74abb32 1145
6a06907d 1146 self.visit_projection(place.as_ref(), context, location);
e74abb32
XL
1147 }
1148
1149 fn super_projection(
1150 &mut self,
6a06907d 1151 place_ref: PlaceRef<'tcx>,
e74abb32
XL
1152 context: PlaceContext,
1153 location: Location,
1154 ) {
064997fb
FG
1155 for (base, elem) in place_ref.iter_projections().rev() {
1156 let base_proj = base.projection;
1157 self.visit_projection_elem(place_ref.local, base_proj, elem, context, location);
e74abb32
XL
1158 }
1159 }
1160
1161 fn super_projection_elem(
1162 &mut self,
74b04a01 1163 _local: Local,
e74abb32 1164 _proj_base: &[PlaceElem<'tcx>],
f9f354fc 1165 elem: PlaceElem<'tcx>,
e74abb32
XL
1166 _context: PlaceContext,
1167 location: Location,
1168 ) {
1169 match elem {
2b03887a 1170 ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
e74abb32
XL
1171 self.visit_ty(ty, TyContext::Location(location));
1172 }
1173 ProjectionElem::Index(local) => {
1174 self.visit_local(
064997fb 1175 local,
e74abb32 1176 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
ba9703b0 1177 location,
e74abb32
XL
1178 );
1179 }
ba9703b0
XL
1180 ProjectionElem::Deref
1181 | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1182 | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1183 | ProjectionElem::Downcast(_, _) => {}
e74abb32
XL
1184 }
1185 }
ba9703b0 1186 };
e74abb32
XL
1187}
1188
9cc50fc6 1189make_mir_visitor!(Visitor,);
dfeec247 1190make_mir_visitor!(MutVisitor, mut);
9cc50fc6 1191
ff7c6d11
XL
1192pub trait MirVisitable<'tcx> {
1193 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
1194}
1195
1196impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
dfeec247 1197 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
48663c56 1198 visitor.visit_statement(self, location)
ff7c6d11
XL
1199 }
1200}
1201
1202impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
dfeec247 1203 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
48663c56 1204 visitor.visit_terminator(self, location)
ff7c6d11
XL
1205 }
1206}
1207
1208impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
dfeec247 1209 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
48663c56 1210 visitor.visit_terminator(self.as_ref().unwrap(), location)
ff7c6d11
XL
1211 }
1212}
1213
abe05a73
XL
1214/// Extra information passed to `visit_ty` and friends to give context
1215/// about where the type etc appears.
e74abb32 1216#[derive(Debug)]
abe05a73
XL
1217pub enum TyContext {
1218 LocalDecl {
1219 /// The index of the local variable we are visiting.
1220 local: Local,
1221
1222 /// The source location where this local variable was declared.
1223 source_info: SourceInfo,
1224 },
1225
9fa01778
XL
1226 /// The inferred type of a user type annotation.
1227 UserTy(Span),
1228
abe05a73
XL
1229 /// The return type of the function.
1230 ReturnTy(SourceInfo),
1231
2c00a5a8
XL
1232 YieldTy(SourceInfo),
1233
abe05a73
XL
1234 /// A type found at some location.
1235 Location(Location),
3b2f2976
XL
1236}
1237
c30ab7b3 1238#[derive(Copy, Clone, Debug, PartialEq, Eq)]
48663c56 1239pub enum NonMutatingUseContext {
13cf67c4
XL
1240 /// Being inspected in some way, like loading a len.
1241 Inspect,
1242 /// Consumed as part of an operand.
1243 Copy,
1244 /// Consumed as part of an operand.
1245 Move,
1246 /// Shared borrow.
48663c56 1247 SharedBorrow,
13cf67c4 1248 /// Shallow borrow.
48663c56 1249 ShallowBorrow,
13cf67c4 1250 /// Unique borrow.
48663c56 1251 UniqueBorrow,
dfeec247
XL
1252 /// AddressOf for *const pointer.
1253 AddressOf,
0731742a 1254 /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
13cf67c4 1255 /// For example, the projection `x.y` is not marked as a mutation in these cases:
04454e1e
FG
1256 /// ```ignore (illustrative)
1257 /// z = x.y;
1258 /// f(&x.y);
1259 /// ```
13cf67c4
XL
1260 Projection,
1261}
92a42be0 1262
13cf67c4 1263#[derive(Copy, Clone, Debug, PartialEq, Eq)]
48663c56 1264pub enum MutatingUseContext {
13cf67c4
XL
1265 /// Appears as LHS of an assignment.
1266 Store,
04454e1e
FG
1267 /// Appears on `SetDiscriminant`
1268 SetDiscriminant,
1269 /// Appears on `Deinit`
1270 Deinit,
a2a8927a 1271 /// Output operand of an inline assembly block.
ff7c6d11 1272 AsmOutput,
13cf67c4 1273 /// Destination of a call.
54a0048b 1274 Call,
f9f354fc
XL
1275 /// Destination of a yield.
1276 Yield,
13cf67c4 1277 /// Being dropped.
92a42be0 1278 Drop,
13cf67c4 1279 /// Mutable borrow.
48663c56 1280 Borrow,
dfeec247
XL
1281 /// AddressOf for *mut pointer.
1282 AddressOf,
0731742a 1283 /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
13cf67c4 1284 /// For example, the projection `x.y` is marked as a mutation in these cases:
04454e1e
FG
1285 /// ```ignore (illustrative)
1286 /// x.y = ...;
1287 /// f(&mut x.y);
1288 /// ```
13cf67c4 1289 Projection,
a1dfa0c6
XL
1290 /// Retagging, a "Stacked Borrows" shadow state operation
1291 Retag,
13cf67c4 1292}
92a42be0 1293
13cf67c4
XL
1294#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1295pub enum NonUseContext {
1296 /// Starting a storage live range.
5bcae85e 1297 StorageLive,
13cf67c4 1298 /// Ending a storage live range.
5bcae85e 1299 StorageDead,
13cf67c4
XL
1300 /// User type annotation assertions for NLL.
1301 AscribeUserTy,
94222f64 1302 /// The data of a user variable, for debug info.
60c5eb7d 1303 VarDebugInfo,
92a42be0 1304}
9e0c209e 1305
13cf67c4 1306#[derive(Copy, Clone, Debug, PartialEq, Eq)]
48663c56
XL
1307pub enum PlaceContext {
1308 NonMutatingUse(NonMutatingUseContext),
1309 MutatingUse(MutatingUseContext),
13cf67c4
XL
1310 NonUse(NonUseContext),
1311}
1312
dc9dc135 1313impl PlaceContext {
13cf67c4 1314 /// Returns `true` if this place context represents a drop.
6a06907d 1315 #[inline]
9e0c209e 1316 pub fn is_drop(&self) -> bool {
29967ef6 1317 matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
13cf67c4
XL
1318 }
1319
1320 /// Returns `true` if this place context represents a borrow.
1321 pub fn is_borrow(&self) -> bool {
29967ef6
XL
1322 matches!(
1323 self,
ba9703b0
XL
1324 PlaceContext::NonMutatingUse(
1325 NonMutatingUseContext::SharedBorrow
29967ef6
XL
1326 | NonMutatingUseContext::ShallowBorrow
1327 | NonMutatingUseContext::UniqueBorrow
1328 ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1329 )
9e0c209e
SL
1330 }
1331
487cf647
FG
1332 /// Returns `true` if this place context represents an address-of.
1333 pub fn is_address_of(&self) -> bool {
1334 matches!(
1335 self,
1336 PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
1337 | PlaceContext::MutatingUse(MutatingUseContext::AddressOf)
1338 )
1339 }
1340
13cf67c4 1341 /// Returns `true` if this place context represents a storage live or storage dead marker.
6a06907d 1342 #[inline]
9e0c209e 1343 pub fn is_storage_marker(&self) -> bool {
29967ef6
XL
1344 matches!(
1345 self,
1346 PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1347 )
9e0c209e
SL
1348 }
1349
13cf67c4 1350 /// Returns `true` if this place context represents a use that potentially changes the value.
6a06907d 1351 #[inline]
9e0c209e 1352 pub fn is_mutating_use(&self) -> bool {
29967ef6 1353 matches!(self, PlaceContext::MutatingUse(..))
9e0c209e
SL
1354 }
1355
13cf67c4 1356 /// Returns `true` if this place context represents a use.
6a06907d 1357 #[inline]
9e0c209e 1358 pub fn is_use(&self) -> bool {
29967ef6 1359 !matches!(self, PlaceContext::NonUse(..))
13cf67c4
XL
1360 }
1361
1362 /// Returns `true` if this place context represents an assignment statement.
1363 pub fn is_place_assignment(&self) -> bool {
29967ef6
XL
1364 matches!(
1365 self,
ba9703b0
XL
1366 PlaceContext::MutatingUse(
1367 MutatingUseContext::Store
29967ef6
XL
1368 | MutatingUseContext::Call
1369 | MutatingUseContext::AsmOutput,
1370 )
1371 )
9e0c209e
SL
1372 }
1373}