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