1 use crate::ty
::subst
::SubstsRef
;
2 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 base
: & $
($mutability
)? PlaceBase
<'tcx
>,
168 context
: PlaceContext
,
169 location
: Location
) {
170 self.super_place_base(base
, 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
{
521 self.visit_operand(value
, source_location
);
527 fn super_assert_message(&mut self,
528 msg
: & $
($mutability
)? AssertMessage
<'tcx
>,
529 location
: Location
) {
530 use crate::mir
::interpret
::PanicInfo
::*;
532 BoundsCheck { len, index }
=> {
533 self.visit_operand(len
, location
);
534 self.visit_operand(index
, location
);
536 Panic { .. }
| Overflow(_
) | OverflowNeg
| DivisionByZero
| RemainderByZero
|
537 ResumedAfterReturn(_
) | ResumedAfterPanic(_
) => {
543 fn super_rvalue(&mut self,
544 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
545 location
: Location
) {
547 Rvalue
::Use(operand
) => {
548 self.visit_operand(operand
, location
);
551 Rvalue
::Repeat(value
, _
) => {
552 self.visit_operand(value
, location
);
555 Rvalue
::Ref(r
, bk
, path
) => {
556 self.visit_region(r
, location
);
558 BorrowKind
::Shared
=> PlaceContext
::NonMutatingUse(
559 NonMutatingUseContext
::SharedBorrow
561 BorrowKind
::Shallow
=> PlaceContext
::NonMutatingUse(
562 NonMutatingUseContext
::ShallowBorrow
564 BorrowKind
::Unique
=> PlaceContext
::NonMutatingUse(
565 NonMutatingUseContext
::UniqueBorrow
567 BorrowKind
::Mut { .. }
=>
568 PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
),
570 self.visit_place(path
, ctx
, location
);
573 Rvalue
::Len(path
) => {
576 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
581 Rvalue
::Cast(_cast_kind
, operand
, ty
) => {
582 self.visit_operand(operand
, location
);
583 self.visit_ty(ty
, TyContext
::Location(location
));
586 Rvalue
::BinaryOp(_bin_op
, lhs
, rhs
)
587 | Rvalue
::CheckedBinaryOp(_bin_op
, lhs
, rhs
) => {
588 self.visit_operand(lhs
, location
);
589 self.visit_operand(rhs
, location
);
592 Rvalue
::UnaryOp(_un_op
, op
) => {
593 self.visit_operand(op
, location
);
596 Rvalue
::Discriminant(place
) => {
599 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
604 Rvalue
::NullaryOp(_op
, ty
) => {
605 self.visit_ty(ty
, TyContext
::Location(location
));
608 Rvalue
::Aggregate(kind
, operands
) => {
609 let kind
= &$
($mutability
)?
**kind
;
611 AggregateKind
::Array(ty
) => {
612 self.visit_ty(ty
, TyContext
::Location(location
));
614 AggregateKind
::Tuple
=> {
623 self.visit_substs(substs
, location
);
625 AggregateKind
::Closure(
629 self.visit_substs(closure_substs
, location
);
631 AggregateKind
::Generator(
636 self.visit_substs(generator_substs
, location
);
640 for operand
in operands
{
641 self.visit_operand(operand
, location
);
647 fn super_operand(&mut self,
648 operand
: & $
($mutability
)? Operand
<'tcx
>,
649 location
: Location
) {
651 Operand
::Copy(place
) => {
654 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
658 Operand
::Move(place
) => {
661 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Move
),
665 Operand
::Constant(constant
) => {
666 self.visit_constant(constant
, location
);
671 fn super_ascribe_user_ty(&mut self,
672 place
: & $
($mutability
)? Place
<'tcx
>,
673 _variance
: & $
($mutability
)? ty
::Variance
,
674 user_ty
: & $
($mutability
)? UserTypeProjection
,
675 location
: Location
) {
678 PlaceContext
::NonUse(NonUseContext
::AscribeUserTy
),
681 self.visit_user_type_projection(user_ty
);
684 fn super_retag(&mut self,
685 _kind
: & $
($mutability
)? RetagKind
,
686 place
: & $
($mutability
)? Place
<'tcx
>,
687 location
: Location
) {
690 PlaceContext
::MutatingUse(MutatingUseContext
::Retag
),
695 fn super_place_base(&mut self,
696 place_base
: & $
($mutability
)? PlaceBase
<'tcx
>,
697 context
: PlaceContext
,
698 location
: Location
) {
700 PlaceBase
::Local(local
) => {
701 self.visit_local(local
, context
, location
);
703 PlaceBase
::Static(box Static { kind: _, ty, def_id: _ }
) => {
704 self.visit_ty(& $
($mutability
)?
*ty
, TyContext
::Location(location
));
709 fn super_local_decl(&mut self,
711 local_decl
: & $
($mutability
)? LocalDecl
<'tcx
>) {
722 self.visit_ty(ty
, TyContext
::LocalDecl
{
724 source_info
: *source_info
,
726 for (user_ty
, _
) in & $
($mutability
)? user_ty
.contents
{
727 self.visit_user_type_projection(user_ty
);
729 self.visit_source_info(source_info
);
732 fn super_var_debug_info(&mut self,
733 var_debug_info
: & $
($mutability
)? VarDebugInfo
<'tcx
>) {
740 self.visit_source_info(source_info
);
741 let location
= START_BLOCK
.start_location();
744 PlaceContext
::NonUse(NonUseContext
::VarDebugInfo
),
749 fn super_source_scope(&mut self,
750 _scope
: & $
($mutability
)? SourceScope
) {
753 fn super_constant(&mut self,
754 constant
: & $
($mutability
)? Constant
<'tcx
>,
755 location
: Location
) {
762 self.visit_span(span
);
763 drop(user_ty
); // no visit method for this
764 self.visit_const(literal
, location
);
767 fn super_span(&mut self, _span
: & $
($mutability
)? Span
) {
770 fn super_source_info(&mut self, source_info
: & $
($mutability
)? SourceInfo
) {
776 self.visit_span(span
);
777 self.visit_source_scope(scope
);
780 fn super_user_type_projection(
782 _ty
: & $
($mutability
)? UserTypeProjection
,
786 fn super_user_type_annotation(
788 _index
: UserTypeAnnotationIndex
,
789 ty
: & $
($mutability
)? CanonicalUserTypeAnnotation
<'tcx
>,
791 self.visit_span(& $
($mutability
)? ty
.span
);
792 self.visit_ty(& $
($mutability
)? ty
.inferred_ty
, TyContext
::UserTy(ty
.span
));
795 fn super_ty(&mut self, _ty
: $
(& $mutability
)? Ty
<'tcx
>) {
798 fn super_region(&mut self, _region
: & $
($mutability
)? ty
::Region
<'tcx
>) {
801 fn super_const(&mut self, _const
: & $
($mutability
)?
&'tcx ty
::Const
<'tcx
>) {
804 fn super_substs(&mut self, _substs
: & $
($mutability
)? SubstsRef
<'tcx
>) {
807 // Convenience methods
811 body
: body_cache_type
!($
($mutability
)? '_
, 'tcx
),
814 let basic_block
= & $
($mutability
)? body
[location
.block
];
815 if basic_block
.statements
.len() == location
.statement_index
{
816 if let Some(ref $
($mutability
)? terminator
) = basic_block
.terminator
{
817 self.visit_terminator(terminator
, location
)
820 let statement
= & $
($mutability
)?
821 basic_block
.statements
[location
.statement_index
];
822 self.visit_statement(statement
, location
)
829 macro_rules
! visit_place_fns
{
831 fn tcx
<'a
>(&'a
self) -> TyCtxt
<'tcx
>;
835 place
: &mut Place
<'tcx
>,
836 context
: PlaceContext
,
839 self.visit_place_base(&mut place
.base
, context
, location
);
841 if let Some(new_projection
) = self.process_projection(&place
.projection
) {
842 place
.projection
= self.tcx().intern_place_elems(&new_projection
);
846 fn process_projection(
848 projection
: &'a
[PlaceElem
<'tcx
>],
849 ) -> Option
<Vec
<PlaceElem
<'tcx
>>> {
850 let mut projection
= Cow
::Borrowed(projection
);
852 for i
in 0..projection
.len() {
853 if let Some(elem
) = projection
.get(i
) {
854 if let Some(elem
) = self.process_projection_elem(elem
) {
855 // This converts the borrowed projection into `Cow::Owned(_)` and returns a
856 // clone of the projection so we can mutate and reintern later.
857 let vec
= projection
.to_mut();
864 Cow
::Borrowed(_
) => None
,
865 Cow
::Owned(vec
) => Some(vec
),
869 fn process_projection_elem(
871 _elem
: &PlaceElem
<'tcx
>,
872 ) -> Option
<PlaceElem
<'tcx
>> {
880 base
: &PlaceBase
<'tcx
>,
881 projection
: &[PlaceElem
<'tcx
>],
882 context
: PlaceContext
,
885 self.super_projection(base
, projection
, context
, location
);
888 fn visit_projection_elem(
890 base
: &PlaceBase
<'tcx
>,
891 proj_base
: &[PlaceElem
<'tcx
>],
892 elem
: &PlaceElem
<'tcx
>,
893 context
: PlaceContext
,
896 self.super_projection_elem(base
, proj_base
, elem
, context
, location
);
902 context
: PlaceContext
,
905 let mut context
= context
;
907 if !place
.projection
.is_empty() {
908 context
= if context
.is_mutating_use() {
909 PlaceContext
::MutatingUse(MutatingUseContext
::Projection
)
911 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Projection
)
915 self.visit_place_base(&place
.base
, context
, location
);
917 self.visit_projection(&place
.base
,
925 base
: &PlaceBase
<'tcx
>,
926 projection
: &[PlaceElem
<'tcx
>],
927 context
: PlaceContext
,
930 let mut cursor
= projection
;
931 while let [proj_base @
.., elem
] = cursor
{
933 self.visit_projection_elem(base
, cursor
, elem
, context
, location
);
937 fn super_projection_elem(
939 _base
: &PlaceBase
<'tcx
>,
940 _proj_base
: &[PlaceElem
<'tcx
>],
941 elem
: &PlaceElem
<'tcx
>,
942 _context
: PlaceContext
,
946 ProjectionElem
::Field(_field
, ty
) => {
947 self.visit_ty(ty
, TyContext
::Location(location
));
949 ProjectionElem
::Index(local
) => {
952 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
956 ProjectionElem
::Deref
|
957 ProjectionElem
::Subslice { from: _, to: _, from_end: _ }
|
958 ProjectionElem
::ConstantIndex
{ offset
: _
,
961 ProjectionElem
::Downcast(_
, _
) => {
968 make_mir_visitor
!(Visitor
,);
969 make_mir_visitor
!(MutVisitor
,mut);
971 pub trait MirVisitable
<'tcx
> {
972 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>);
975 impl<'tcx
> MirVisitable
<'tcx
> for Statement
<'tcx
> {
976 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>)
978 visitor
.visit_statement(self, location
)
982 impl<'tcx
> MirVisitable
<'tcx
> for Terminator
<'tcx
> {
983 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>)
985 visitor
.visit_terminator(self, location
)
989 impl<'tcx
> MirVisitable
<'tcx
> for Option
<Terminator
<'tcx
>> {
990 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>)
992 visitor
.visit_terminator(self.as_ref().unwrap(), location
)
996 /// Extra information passed to `visit_ty` and friends to give context
997 /// about where the type etc appears.
1001 /// The index of the local variable we are visiting.
1004 /// The source location where this local variable was declared.
1005 source_info
: SourceInfo
,
1008 /// The inferred type of a user type annotation.
1011 /// The return type of the function.
1012 ReturnTy(SourceInfo
),
1014 YieldTy(SourceInfo
),
1016 /// A type found at some location.
1020 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1021 pub enum NonMutatingUseContext
{
1022 /// Being inspected in some way, like loading a len.
1024 /// Consumed as part of an operand.
1026 /// Consumed as part of an operand.
1034 /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1035 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1043 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1044 pub enum MutatingUseContext
{
1045 /// Appears as LHS of an assignment.
1047 /// Can often be treated as a `Store`, but needs to be separate because
1048 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1049 /// cannot be simplified the way a `Store`-`Store` can be.
1051 /// Destination of a call.
1057 /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1058 /// For example, the projection `x.y` is marked as a mutation in these cases:
1064 /// Retagging, a "Stacked Borrows" shadow state operation
1068 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1069 pub enum NonUseContext
{
1070 /// Starting a storage live range.
1072 /// Ending a storage live range.
1074 /// User type annotation assertions for NLL.
1076 /// The data of an user variable, for debug info.
1080 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1081 pub enum PlaceContext
{
1082 NonMutatingUse(NonMutatingUseContext
),
1083 MutatingUse(MutatingUseContext
),
1084 NonUse(NonUseContext
),
1088 /// Returns `true` if this place context represents a drop.
1089 pub fn is_drop(&self) -> bool
{
1091 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
) => true,
1096 /// Returns `true` if this place context represents a borrow.
1097 pub fn is_borrow(&self) -> bool
{
1099 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::SharedBorrow
) |
1100 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::ShallowBorrow
) |
1101 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::UniqueBorrow
) |
1102 PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
) => true,
1107 /// Returns `true` if this place context represents a storage live or storage dead marker.
1108 pub fn is_storage_marker(&self) -> bool
{
1110 PlaceContext
::NonUse(NonUseContext
::StorageLive
) |
1111 PlaceContext
::NonUse(NonUseContext
::StorageDead
) => true,
1116 /// Returns `true` if this place context represents a storage live marker.
1117 pub fn is_storage_live_marker(&self) -> bool
{
1119 PlaceContext
::NonUse(NonUseContext
::StorageLive
) => true,
1124 /// Returns `true` if this place context represents a storage dead marker.
1125 pub fn is_storage_dead_marker(&self) -> bool
{
1127 PlaceContext
::NonUse(NonUseContext
::StorageDead
) => true,
1132 /// Returns `true` if this place context represents a use that potentially changes the value.
1133 pub fn is_mutating_use(&self) -> bool
{
1135 PlaceContext
::MutatingUse(..) => true,
1140 /// Returns `true` if this place context represents a use that does not change the value.
1141 pub fn is_nonmutating_use(&self) -> bool
{
1143 PlaceContext
::NonMutatingUse(..) => true,
1148 /// Returns `true` if this place context represents a use.
1149 pub fn is_use(&self) -> bool
{
1151 PlaceContext
::NonUse(..) => false,
1156 /// Returns `true` if this place context represents an assignment statement.
1157 pub fn is_place_assignment(&self) -> bool
{
1159 PlaceContext
::MutatingUse(MutatingUseContext
::Store
) |
1160 PlaceContext
::MutatingUse(MutatingUseContext
::Call
) |
1161 PlaceContext
::MutatingUse(MutatingUseContext
::AsmOutput
) => true,