2 use crate::ty
::subst
::SubstsRef
;
3 use crate::ty
::{CanonicalUserTypeAnnotation, Ty}
;
10 // There are two visitors, one for immutable and one for mutable references,
11 // but both are generated by the following macro. The code is written according
12 // to the following conventions:
14 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
15 // - `visit_foo`, by default, calls `super_foo`
16 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
18 // This allows you as a user to override `visit_foo` for types are
19 // interested in, and invoke (within that method) call
20 // `self.super_foo` to get the default behavior. Just as in an OO
21 // language, you should never call `super` methods ordinarily except
22 // in that circumstance.
24 // For the most part, we do not destructure things external to the
25 // MIR, e.g., types, spans, etc, but simply visit them and stop. This
26 // avoids duplication with other visitors like `TypeFoldable`.
30 // The code is written in a very deliberate style intended to minimize
31 // the chance of things being overlooked. You'll notice that we always
32 // use pattern matching to reference fields and we ensure that all
33 // matches are exhaustive.
35 // For example, the `super_basic_block_data` method begins like this:
38 // fn super_basic_block_data(&mut self,
40 // data: & $($mutability)? BasicBlockData<'tcx>) {
41 // let BasicBlockData {
47 // for statement in statements {
48 // self.visit_statement(block, statement);
55 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
56 // rather than writing `data.statements` in the body. This is because if one
57 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
58 // and hence one will (hopefully) invoke the correct visit methods (if any).
60 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
61 // That means you never write `..` to skip over fields, nor do you write `_`
62 // to skip over variants in a `match`.
64 // The only place that `_` is acceptable is to match a field (or
65 // variant argument) that does not require visiting, as in
66 // `is_cleanup` above.
68 macro_rules
! body_cache_type
{
69 (mut $a
:lifetime
, $tcx
:lifetime
) => {
70 &mut BodyAndCache
<$tcx
>
72 ($a
:lifetime
, $tcx
:lifetime
) => {
73 ReadOnlyBodyAndCache
<$a
, $tcx
>
77 macro_rules
! make_mir_visitor
{
78 ($visitor_trait_name
:ident
, $
($mutability
:ident
)?
) => {
79 pub trait $visitor_trait_name
<'tcx
> {
80 // Override these, and call `self.super_xxx` to revert back to the
85 body
: body_cache_type
!($
($mutability
)? '_
, 'tcx
)
87 self.super_body(body
);
90 fn visit_basic_block_data(&mut self,
92 data
: & $
($mutability
)? BasicBlockData
<'tcx
>) {
93 self.super_basic_block_data(block
, data
);
96 fn visit_source_scope_data(&mut self,
97 scope_data
: & $
($mutability
)? SourceScopeData
) {
98 self.super_source_scope_data(scope_data
);
101 fn visit_statement(&mut self,
102 statement
: & $
($mutability
)? Statement
<'tcx
>,
103 location
: Location
) {
104 self.super_statement(statement
, location
);
107 fn visit_assign(&mut self,
108 place
: & $
($mutability
)? Place
<'tcx
>,
109 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
110 location
: Location
) {
111 self.super_assign(place
, rvalue
, location
);
114 fn visit_terminator(&mut self,
115 terminator
: & $
($mutability
)? Terminator
<'tcx
>,
116 location
: Location
) {
117 self.super_terminator(terminator
, location
);
120 fn visit_terminator_kind(&mut self,
121 kind
: & $
($mutability
)? TerminatorKind
<'tcx
>,
122 location
: Location
) {
123 self.super_terminator_kind(kind
, location
);
126 fn visit_assert_message(&mut self,
127 msg
: & $
($mutability
)? AssertMessage
<'tcx
>,
128 location
: Location
) {
129 self.super_assert_message(msg
, location
);
132 fn visit_rvalue(&mut self,
133 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
134 location
: Location
) {
135 self.super_rvalue(rvalue
, location
);
138 fn visit_operand(&mut self,
139 operand
: & $
($mutability
)? Operand
<'tcx
>,
140 location
: Location
) {
141 self.super_operand(operand
, location
);
144 fn visit_ascribe_user_ty(&mut self,
145 place
: & $
($mutability
)? Place
<'tcx
>,
146 variance
: & $
($mutability
)? ty
::Variance
,
147 user_ty
: & $
($mutability
)? UserTypeProjection
,
148 location
: Location
) {
149 self.super_ascribe_user_ty(place
, variance
, user_ty
, location
);
152 fn visit_retag(&mut self,
153 kind
: & $
($mutability
)? RetagKind
,
154 place
: & $
($mutability
)? Place
<'tcx
>,
155 location
: Location
) {
156 self.super_retag(kind
, place
, location
);
159 fn visit_place(&mut self,
160 place
: & $
($mutability
)? Place
<'tcx
>,
161 context
: PlaceContext
,
162 location
: Location
) {
163 self.super_place(place
, context
, location
);
166 fn visit_place_base(&mut self,
167 local
: & $
($mutability
)? Local
,
168 context
: PlaceContext
,
169 location
: Location
) {
170 self.super_place_base(local
, context
, location
);
173 visit_place_fns
!($
($mutability
)?
);
175 fn visit_constant(&mut self,
176 constant
: & $
($mutability
)? Constant
<'tcx
>,
177 location
: Location
) {
178 self.super_constant(constant
, location
);
181 fn visit_span(&mut self,
182 span
: & $
($mutability
)? Span
) {
183 self.super_span(span
);
186 fn visit_source_info(&mut self,
187 source_info
: & $
($mutability
)? SourceInfo
) {
188 self.super_source_info(source_info
);
191 fn visit_ty(&mut self,
192 ty
: $
(& $mutability
)? Ty
<'tcx
>,
197 fn visit_user_type_projection(
199 ty
: & $
($mutability
)? UserTypeProjection
,
201 self.super_user_type_projection(ty
);
204 fn visit_user_type_annotation(
206 index
: UserTypeAnnotationIndex
,
207 ty
: & $
($mutability
)? CanonicalUserTypeAnnotation
<'tcx
>,
209 self.super_user_type_annotation(index
, ty
);
212 fn visit_region(&mut self,
213 region
: & $
($mutability
)? ty
::Region
<'tcx
>,
215 self.super_region(region
);
218 fn visit_const(&mut self,
219 constant
: & $
($mutability
)?
&'tcx ty
::Const
<'tcx
>,
221 self.super_const(constant
);
224 fn visit_substs(&mut self,
225 substs
: & $
($mutability
)? SubstsRef
<'tcx
>,
227 self.super_substs(substs
);
230 fn visit_local_decl(&mut self,
232 local_decl
: & $
($mutability
)? LocalDecl
<'tcx
>) {
233 self.super_local_decl(local
, local_decl
);
236 fn visit_var_debug_info(&mut self,
237 var_debug_info
: & $
($mutability
)* VarDebugInfo
<'tcx
>) {
238 self.super_var_debug_info(var_debug_info
);
241 fn visit_local(&mut self,
242 _local
: & $
($mutability
)? Local
,
243 _context
: PlaceContext
,
244 _location
: Location
) {
247 fn visit_source_scope(&mut self,
248 scope
: & $
($mutability
)? SourceScope
) {
249 self.super_source_scope(scope
);
252 // The `super_xxx` methods comprise the default behavior and are
253 // not meant to be overridden.
257 $
($mutability
)? body
: body_cache_type
!($
($mutability
)? '_
, 'tcx
)
259 let span
= body
.span
;
260 if let Some(yield_ty
) = &$
($mutability
)? body
.yield_ty
{
261 self.visit_ty(yield_ty
, TyContext
::YieldTy(SourceInfo
{
263 scope
: OUTERMOST_SOURCE_SCOPE
,
267 // for best performance, we want to use an iterator rather
268 // than a for-loop, to avoid calling `body::Body::invalidate` for
270 macro_rules
! basic_blocks
{
271 (mut) => (body
.basic_blocks_mut().iter_enumerated_mut());
272 () => (body
.basic_blocks().iter_enumerated());
274 for (bb
, data
) in basic_blocks
!($
($mutability
)?
) {
275 self.visit_basic_block_data(bb
, data
);
278 let body
: & $
($mutability
)? Body
<'_
> = & $
($mutability
)? body
;
279 for scope
in &$
($mutability
)? body
.source_scopes
{
280 self.visit_source_scope_data(scope
);
283 self.visit_ty(&$
($mutability
)? body
.return_ty(), TyContext
::ReturnTy(SourceInfo
{
285 scope
: OUTERMOST_SOURCE_SCOPE
,
288 for local
in body
.local_decls
.indices() {
289 self.visit_local_decl(local
, & $
($mutability
)? body
.local_decls
[local
]);
292 macro_rules
! type_annotations
{
293 (mut) => (body
.user_type_annotations
.iter_enumerated_mut());
294 () => (body
.user_type_annotations
.iter_enumerated());
297 for (index
, annotation
) in type_annotations
!($
($mutability
)?
) {
298 self.visit_user_type_annotation(
303 for var_debug_info
in &$
($mutability
)? body
.var_debug_info
{
304 self.visit_var_debug_info(var_debug_info
);
307 self.visit_span(&$
($mutability
)? body
.span
);
310 fn super_basic_block_data(&mut self,
312 data
: & $
($mutability
)? BasicBlockData
<'tcx
>) {
320 for statement
in statements
{
321 let location
= Location { block: block, statement_index: index }
;
322 self.visit_statement(statement
, location
);
326 if let Some(terminator
) = terminator
{
327 let location
= Location { block: block, statement_index: index }
;
328 self.visit_terminator(terminator
, location
);
332 fn super_source_scope_data(&mut self, scope_data
: & $
($mutability
)? SourceScopeData
) {
333 let SourceScopeData
{
339 self.visit_span(span
);
340 if let Some(parent_scope
) = parent_scope
{
341 self.visit_source_scope(parent_scope
);
345 fn super_statement(&mut self,
346 statement
: & $
($mutability
)? Statement
<'tcx
>,
347 location
: Location
) {
353 self.visit_source_info(source_info
);
355 StatementKind
::Assign(
356 box(ref $
($mutability
)? place
, ref $
($mutability
)? rvalue
)
358 self.visit_assign(place
, rvalue
, location
);
360 StatementKind
::FakeRead(_
, place
) => {
363 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
367 StatementKind
::SetDiscriminant { place, .. }
=> {
370 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
374 StatementKind
::StorageLive(local
) => {
377 PlaceContext
::NonUse(NonUseContext
::StorageLive
),
381 StatementKind
::StorageDead(local
) => {
384 PlaceContext
::NonUse(NonUseContext
::StorageDead
),
388 StatementKind
::InlineAsm(asm
) => {
389 for output
in & $
($mutability
)? asm
.outputs
[..] {
392 PlaceContext
::MutatingUse(MutatingUseContext
::AsmOutput
),
396 for (span
, input
) in & $
($mutability
)? asm
.inputs
[..] {
397 self.visit_span(span
);
398 self.visit_operand(input
, location
);
401 StatementKind
::Retag(kind
, place
) => {
402 self.visit_retag(kind
, place
, location
);
404 StatementKind
::AscribeUserType(
405 box(ref $
($mutability
)? place
, ref $
($mutability
)? user_ty
),
408 self.visit_ascribe_user_ty(place
, variance
, user_ty
, location
);
410 StatementKind
::Nop
=> {}
414 fn super_assign(&mut self,
415 place
: &$
($mutability
)? Place
<'tcx
>,
416 rvalue
: &$
($mutability
)? Rvalue
<'tcx
>,
417 location
: Location
) {
420 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
423 self.visit_rvalue(rvalue
, location
);
426 fn super_terminator(&mut self,
427 terminator
: &$
($mutability
)? Terminator
<'tcx
>,
428 location
: Location
) {
429 let Terminator { source_info, kind }
= terminator
;
431 self.visit_source_info(source_info
);
432 self.visit_terminator_kind(kind
, location
);
435 fn super_terminator_kind(&mut self,
436 kind
: & $
($mutability
)? TerminatorKind
<'tcx
>,
437 source_location
: Location
) {
439 TerminatorKind
::Goto { .. }
|
440 TerminatorKind
::Resume
|
441 TerminatorKind
::Abort
|
442 TerminatorKind
::Return
|
443 TerminatorKind
::GeneratorDrop
|
444 TerminatorKind
::Unreachable
|
445 TerminatorKind
::FalseEdges { .. }
|
446 TerminatorKind
::FalseUnwind { .. }
=> {
449 TerminatorKind
::SwitchInt
{
455 self.visit_operand(discr
, source_location
);
456 self.visit_ty(switch_ty
, TyContext
::Location(source_location
));
459 TerminatorKind
::Drop
{
466 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
),
471 TerminatorKind
::DropAndReplace
{
479 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
),
482 self.visit_operand(value
, source_location
);
485 TerminatorKind
::Call
{
492 self.visit_operand(func
, source_location
);
494 self.visit_operand(arg
, source_location
);
496 if let Some((destination
, _
)) = destination
{
499 PlaceContext
::MutatingUse(MutatingUseContext
::Call
),
505 TerminatorKind
::Assert
{
512 self.visit_operand(cond
, source_location
);
513 self.visit_assert_message(msg
, source_location
);
516 TerminatorKind
::Yield
{
522 self.visit_operand(value
, source_location
);
525 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
533 fn super_assert_message(&mut self,
534 msg
: & $
($mutability
)? AssertMessage
<'tcx
>,
535 location
: Location
) {
536 use crate::mir
::AssertKind
::*;
538 BoundsCheck { len, index }
=> {
539 self.visit_operand(len
, location
);
540 self.visit_operand(index
, location
);
542 Overflow(_
) | OverflowNeg
| DivisionByZero
| RemainderByZero
|
543 ResumedAfterReturn(_
) | ResumedAfterPanic(_
) => {
549 fn super_rvalue(&mut self,
550 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
551 location
: Location
) {
553 Rvalue
::Use(operand
) => {
554 self.visit_operand(operand
, location
);
557 Rvalue
::Repeat(value
, _
) => {
558 self.visit_operand(value
, location
);
561 Rvalue
::Ref(r
, bk
, path
) => {
562 self.visit_region(r
, location
);
564 BorrowKind
::Shared
=> PlaceContext
::NonMutatingUse(
565 NonMutatingUseContext
::SharedBorrow
567 BorrowKind
::Shallow
=> PlaceContext
::NonMutatingUse(
568 NonMutatingUseContext
::ShallowBorrow
570 BorrowKind
::Unique
=> PlaceContext
::NonMutatingUse(
571 NonMutatingUseContext
::UniqueBorrow
573 BorrowKind
::Mut { .. }
=>
574 PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
),
576 self.visit_place(path
, ctx
, location
);
579 Rvalue
::AddressOf(m
, path
) => {
581 Mutability
::Mut
=> PlaceContext
::MutatingUse(
582 MutatingUseContext
::AddressOf
584 Mutability
::Not
=> PlaceContext
::NonMutatingUse(
585 NonMutatingUseContext
::AddressOf
588 self.visit_place(path
, ctx
, location
);
591 Rvalue
::Len(path
) => {
594 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
599 Rvalue
::Cast(_cast_kind
, operand
, ty
) => {
600 self.visit_operand(operand
, location
);
601 self.visit_ty(ty
, TyContext
::Location(location
));
604 Rvalue
::BinaryOp(_bin_op
, lhs
, rhs
)
605 | Rvalue
::CheckedBinaryOp(_bin_op
, lhs
, rhs
) => {
606 self.visit_operand(lhs
, location
);
607 self.visit_operand(rhs
, location
);
610 Rvalue
::UnaryOp(_un_op
, op
) => {
611 self.visit_operand(op
, location
);
614 Rvalue
::Discriminant(place
) => {
617 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
622 Rvalue
::NullaryOp(_op
, ty
) => {
623 self.visit_ty(ty
, TyContext
::Location(location
));
626 Rvalue
::Aggregate(kind
, operands
) => {
627 let kind
= &$
($mutability
)?
**kind
;
629 AggregateKind
::Array(ty
) => {
630 self.visit_ty(ty
, TyContext
::Location(location
));
632 AggregateKind
::Tuple
=> {
641 self.visit_substs(substs
, location
);
643 AggregateKind
::Closure(
647 self.visit_substs(closure_substs
, location
);
649 AggregateKind
::Generator(
654 self.visit_substs(generator_substs
, location
);
658 for operand
in operands
{
659 self.visit_operand(operand
, location
);
665 fn super_operand(&mut self,
666 operand
: & $
($mutability
)? Operand
<'tcx
>,
667 location
: Location
) {
669 Operand
::Copy(place
) => {
672 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
676 Operand
::Move(place
) => {
679 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Move
),
683 Operand
::Constant(constant
) => {
684 self.visit_constant(constant
, location
);
689 fn super_ascribe_user_ty(&mut self,
690 place
: & $
($mutability
)? Place
<'tcx
>,
691 _variance
: & $
($mutability
)? ty
::Variance
,
692 user_ty
: & $
($mutability
)? UserTypeProjection
,
693 location
: Location
) {
696 PlaceContext
::NonUse(NonUseContext
::AscribeUserTy
),
699 self.visit_user_type_projection(user_ty
);
702 fn super_retag(&mut self,
703 _kind
: & $
($mutability
)? RetagKind
,
704 place
: & $
($mutability
)? Place
<'tcx
>,
705 location
: Location
) {
708 PlaceContext
::MutatingUse(MutatingUseContext
::Retag
),
713 fn super_place_base(&mut self,
714 local
: & $
($mutability
)? Local
,
715 context
: PlaceContext
,
716 location
: Location
) {
717 self.visit_local(local
, context
, location
);
720 fn super_local_decl(&mut self,
722 local_decl
: & $
($mutability
)? LocalDecl
<'tcx
>) {
733 self.visit_ty(ty
, TyContext
::LocalDecl
{
735 source_info
: *source_info
,
737 for (user_ty
, _
) in & $
($mutability
)? user_ty
.contents
{
738 self.visit_user_type_projection(user_ty
);
740 self.visit_source_info(source_info
);
743 fn super_var_debug_info(&mut self,
744 var_debug_info
: & $
($mutability
)? VarDebugInfo
<'tcx
>) {
751 self.visit_source_info(source_info
);
752 let location
= START_BLOCK
.start_location();
755 PlaceContext
::NonUse(NonUseContext
::VarDebugInfo
),
760 fn super_source_scope(&mut self,
761 _scope
: & $
($mutability
)? SourceScope
) {
764 fn super_constant(&mut self,
765 constant
: & $
($mutability
)? Constant
<'tcx
>,
766 location
: Location
) {
773 self.visit_span(span
);
774 drop(user_ty
); // no visit method for this
775 self.visit_const(literal
, location
);
778 fn super_span(&mut self, _span
: & $
($mutability
)? Span
) {
781 fn super_source_info(&mut self, source_info
: & $
($mutability
)? SourceInfo
) {
787 self.visit_span(span
);
788 self.visit_source_scope(scope
);
791 fn super_user_type_projection(
793 _ty
: & $
($mutability
)? UserTypeProjection
,
797 fn super_user_type_annotation(
799 _index
: UserTypeAnnotationIndex
,
800 ty
: & $
($mutability
)? CanonicalUserTypeAnnotation
<'tcx
>,
802 self.visit_span(& $
($mutability
)? ty
.span
);
803 self.visit_ty(& $
($mutability
)? ty
.inferred_ty
, TyContext
::UserTy(ty
.span
));
806 fn super_ty(&mut self, _ty
: $
(& $mutability
)? Ty
<'tcx
>) {
809 fn super_region(&mut self, _region
: & $
($mutability
)? ty
::Region
<'tcx
>) {
812 fn super_const(&mut self, _const
: & $
($mutability
)?
&'tcx ty
::Const
<'tcx
>) {
815 fn super_substs(&mut self, _substs
: & $
($mutability
)? SubstsRef
<'tcx
>) {
818 // Convenience methods
822 body
: body_cache_type
!($
($mutability
)? '_
, 'tcx
),
825 let basic_block
= & $
($mutability
)? body
[location
.block
];
826 if basic_block
.statements
.len() == location
.statement_index
{
827 if let Some(ref $
($mutability
)? terminator
) = basic_block
.terminator
{
828 self.visit_terminator(terminator
, location
)
831 let statement
= & $
($mutability
)?
832 basic_block
.statements
[location
.statement_index
];
833 self.visit_statement(statement
, location
)
840 macro_rules
! visit_place_fns
{
842 fn tcx
<'a
>(&'a
self) -> TyCtxt
<'tcx
>;
846 place
: &mut Place
<'tcx
>,
847 context
: PlaceContext
,
850 self.visit_place_base(&mut place
.local
, context
, location
);
852 if let Some(new_projection
) = self.process_projection(&place
.projection
) {
853 place
.projection
= self.tcx().intern_place_elems(&new_projection
);
857 fn process_projection(
859 projection
: &'a
[PlaceElem
<'tcx
>],
860 ) -> Option
<Vec
<PlaceElem
<'tcx
>>> {
861 let mut projection
= Cow
::Borrowed(projection
);
863 for i
in 0..projection
.len() {
864 if let Some(elem
) = projection
.get(i
) {
865 if let Some(elem
) = self.process_projection_elem(elem
) {
866 // This converts the borrowed projection into `Cow::Owned(_)` and returns a
867 // clone of the projection so we can mutate and reintern later.
868 let vec
= projection
.to_mut();
875 Cow
::Borrowed(_
) => None
,
876 Cow
::Owned(vec
) => Some(vec
),
880 fn process_projection_elem(
882 _elem
: &PlaceElem
<'tcx
>,
883 ) -> Option
<PlaceElem
<'tcx
>> {
892 projection
: &[PlaceElem
<'tcx
>],
893 context
: PlaceContext
,
896 self.super_projection(local
, projection
, context
, location
);
899 fn visit_projection_elem(
902 proj_base
: &[PlaceElem
<'tcx
>],
903 elem
: &PlaceElem
<'tcx
>,
904 context
: PlaceContext
,
907 self.super_projection_elem(local
, proj_base
, elem
, context
, location
);
913 context
: PlaceContext
,
916 let mut context
= context
;
918 if !place
.projection
.is_empty() {
919 context
= if context
.is_mutating_use() {
920 PlaceContext
::MutatingUse(MutatingUseContext
::Projection
)
922 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Projection
)
926 self.visit_place_base(&place
.local
, context
, location
);
928 self.visit_projection(place
.local
,
937 projection
: &[PlaceElem
<'tcx
>],
938 context
: PlaceContext
,
941 let mut cursor
= projection
;
942 while let [proj_base @
.., elem
] = cursor
{
944 self.visit_projection_elem(local
, cursor
, elem
, context
, location
);
948 fn super_projection_elem(
951 _proj_base
: &[PlaceElem
<'tcx
>],
952 elem
: &PlaceElem
<'tcx
>,
953 _context
: PlaceContext
,
957 ProjectionElem
::Field(_field
, ty
) => {
958 self.visit_ty(ty
, TyContext
::Location(location
));
960 ProjectionElem
::Index(local
) => {
963 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
967 ProjectionElem
::Deref
|
968 ProjectionElem
::Subslice { from: _, to: _, from_end: _ }
|
969 ProjectionElem
::ConstantIndex
{ offset
: _
,
972 ProjectionElem
::Downcast(_
, _
) => {
979 make_mir_visitor
!(Visitor
,);
980 make_mir_visitor
!(MutVisitor
, mut);
982 pub trait MirVisitable
<'tcx
> {
983 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>);
986 impl<'tcx
> MirVisitable
<'tcx
> for Statement
<'tcx
> {
987 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
988 visitor
.visit_statement(self, location
)
992 impl<'tcx
> MirVisitable
<'tcx
> for Terminator
<'tcx
> {
993 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
994 visitor
.visit_terminator(self, location
)
998 impl<'tcx
> MirVisitable
<'tcx
> for Option
<Terminator
<'tcx
>> {
999 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
1000 visitor
.visit_terminator(self.as_ref().unwrap(), location
)
1004 /// Extra information passed to `visit_ty` and friends to give context
1005 /// about where the type etc appears.
1007 pub enum TyContext
{
1009 /// The index of the local variable we are visiting.
1012 /// The source location where this local variable was declared.
1013 source_info
: SourceInfo
,
1016 /// The inferred type of a user type annotation.
1019 /// The return type of the function.
1020 ReturnTy(SourceInfo
),
1022 YieldTy(SourceInfo
),
1024 /// A type found at some location.
1028 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1029 pub enum NonMutatingUseContext
{
1030 /// Being inspected in some way, like loading a len.
1032 /// Consumed as part of an operand.
1034 /// Consumed as part of an operand.
1042 /// AddressOf for *const pointer.
1044 /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1045 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1053 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1054 pub enum MutatingUseContext
{
1055 /// Appears as LHS of an assignment.
1057 /// Can often be treated as a `Store`, but needs to be separate because
1058 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1059 /// cannot be simplified the way a `Store`-`Store` can be.
1061 /// Destination of a call.
1067 /// AddressOf for *mut pointer.
1069 /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1070 /// For example, the projection `x.y` is marked as a mutation in these cases:
1076 /// Retagging, a "Stacked Borrows" shadow state operation
1080 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1081 pub enum NonUseContext
{
1082 /// Starting a storage live range.
1084 /// Ending a storage live range.
1086 /// User type annotation assertions for NLL.
1088 /// The data of an user variable, for debug info.
1092 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1093 pub enum PlaceContext
{
1094 NonMutatingUse(NonMutatingUseContext
),
1095 MutatingUse(MutatingUseContext
),
1096 NonUse(NonUseContext
),
1100 /// Returns `true` if this place context represents a drop.
1101 pub fn is_drop(&self) -> bool
{
1103 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
) => true,
1108 /// Returns `true` if this place context represents a borrow.
1109 pub fn is_borrow(&self) -> bool
{
1111 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::SharedBorrow
)
1112 | PlaceContext
::NonMutatingUse(NonMutatingUseContext
::ShallowBorrow
)
1113 | PlaceContext
::NonMutatingUse(NonMutatingUseContext
::UniqueBorrow
)
1114 | PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
) => true,
1119 /// Returns `true` if this place context represents a storage live or storage dead marker.
1120 pub fn is_storage_marker(&self) -> bool
{
1122 PlaceContext
::NonUse(NonUseContext
::StorageLive
)
1123 | PlaceContext
::NonUse(NonUseContext
::StorageDead
) => true,
1128 /// Returns `true` if this place context represents a storage live marker.
1129 pub fn is_storage_live_marker(&self) -> bool
{
1131 PlaceContext
::NonUse(NonUseContext
::StorageLive
) => true,
1136 /// Returns `true` if this place context represents a storage dead marker.
1137 pub fn is_storage_dead_marker(&self) -> bool
{
1139 PlaceContext
::NonUse(NonUseContext
::StorageDead
) => true,
1144 /// Returns `true` if this place context represents a use that potentially changes the value.
1145 pub fn is_mutating_use(&self) -> bool
{
1147 PlaceContext
::MutatingUse(..) => true,
1152 /// Returns `true` if this place context represents a use that does not change the value.
1153 pub fn is_nonmutating_use(&self) -> bool
{
1155 PlaceContext
::NonMutatingUse(..) => true,
1160 /// Returns `true` if this place context represents a use.
1161 pub fn is_use(&self) -> bool
{
1163 PlaceContext
::NonUse(..) => false,
1168 /// Returns `true` if this place context represents an assignment statement.
1169 pub fn is_place_assignment(&self) -> bool
{
1171 PlaceContext
::MutatingUse(MutatingUseContext
::Store
)
1172 | PlaceContext
::MutatingUse(MutatingUseContext
::Call
)
1173 | PlaceContext
::MutatingUse(MutatingUseContext
::AsmOutput
) => true,