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