]>
Commit | Line | Data |
---|---|---|
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 | 65 | use crate::mir::*; |
4b012472 | 66 | use crate::ty::CanonicalUserTypeAnnotation; |
92a42be0 | 67 | |
9cc50fc6 | 68 | macro_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 |
956 | macro_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 | ||
968 | macro_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 | ||
977 | macro_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 | ||
990 | macro_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 | 1044 | macro_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 | 1203 | make_mir_visitor!(Visitor,); |
dfeec247 | 1204 | make_mir_visitor!(MutVisitor, mut); |
9cc50fc6 | 1205 | |
ff7c6d11 XL |
1206 | pub trait MirVisitable<'tcx> { |
1207 | fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>); | |
1208 | } | |
1209 | ||
1210 | impl<'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 | ||
1216 | impl<'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 | ||
1222 | impl<'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 |
1231 | pub 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 | 1253 | pub 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 | 1281 | pub 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)] |
1312 | pub 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 |
1324 | pub enum PlaceContext { |
1325 | NonMutatingUse(NonMutatingUseContext), | |
1326 | MutatingUse(MutatingUseContext), | |
13cf67c4 XL |
1327 | NonUse(NonUseContext), |
1328 | } | |
1329 | ||
dc9dc135 | 1330 | impl 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 | } |