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
! make_mir_visitor
{
69 ($visitor_trait_name
:ident
, $
($mutability
:ident
)?
) => {
70 pub trait $visitor_trait_name
<'tcx
> {
71 // Override these, and call `self.super_xxx` to revert back to the
76 body
: &$
($mutability
)? Body
<'tcx
>,
78 self.super_body(body
);
81 fn visit_basic_block_data(&mut self,
83 data
: & $
($mutability
)? BasicBlockData
<'tcx
>) {
84 self.super_basic_block_data(block
, data
);
87 fn visit_source_scope_data(&mut self,
88 scope_data
: & $
($mutability
)? SourceScopeData
) {
89 self.super_source_scope_data(scope_data
);
92 fn visit_statement(&mut self,
93 statement
: & $
($mutability
)? Statement
<'tcx
>,
95 self.super_statement(statement
, location
);
98 fn visit_assign(&mut self,
99 place
: & $
($mutability
)? Place
<'tcx
>,
100 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
101 location
: Location
) {
102 self.super_assign(place
, rvalue
, location
);
105 fn visit_terminator(&mut self,
106 terminator
: & $
($mutability
)? Terminator
<'tcx
>,
107 location
: Location
) {
108 self.super_terminator(terminator
, location
);
111 fn visit_assert_message(&mut self,
112 msg
: & $
($mutability
)? AssertMessage
<'tcx
>,
113 location
: Location
) {
114 self.super_assert_message(msg
, location
);
117 fn visit_rvalue(&mut self,
118 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
119 location
: Location
) {
120 self.super_rvalue(rvalue
, location
);
123 fn visit_operand(&mut self,
124 operand
: & $
($mutability
)? Operand
<'tcx
>,
125 location
: Location
) {
126 self.super_operand(operand
, location
);
129 fn visit_ascribe_user_ty(&mut self,
130 place
: & $
($mutability
)? Place
<'tcx
>,
131 variance
: & $
($mutability
)? ty
::Variance
,
132 user_ty
: & $
($mutability
)? UserTypeProjection
,
133 location
: Location
) {
134 self.super_ascribe_user_ty(place
, variance
, user_ty
, location
);
137 fn visit_coverage(&mut self,
138 coverage
: & $
($mutability
)? Coverage
,
139 location
: Location
) {
140 self.super_coverage(coverage
, location
);
143 fn visit_retag(&mut self,
144 kind
: & $
($mutability
)? RetagKind
,
145 place
: & $
($mutability
)? Place
<'tcx
>,
146 location
: Location
) {
147 self.super_retag(kind
, place
, location
);
150 fn visit_place(&mut self,
151 place
: & $
($mutability
)? Place
<'tcx
>,
152 context
: PlaceContext
,
153 location
: Location
) {
154 self.super_place(place
, context
, location
);
157 visit_place_fns
!($
($mutability
)?
);
159 fn visit_constant(&mut self,
160 constant
: & $
($mutability
)? Constant
<'tcx
>,
161 location
: Location
) {
162 self.super_constant(constant
, location
);
165 fn visit_span(&mut self,
166 span
: & $
($mutability
)? Span
) {
167 self.super_span(span
);
170 fn visit_source_info(&mut self,
171 source_info
: & $
($mutability
)? SourceInfo
) {
172 self.super_source_info(source_info
);
175 fn visit_ty(&mut self,
176 ty
: $
(& $mutability
)? Ty
<'tcx
>,
181 fn visit_user_type_projection(
183 ty
: & $
($mutability
)? UserTypeProjection
,
185 self.super_user_type_projection(ty
);
188 fn visit_user_type_annotation(
190 index
: UserTypeAnnotationIndex
,
191 ty
: & $
($mutability
)? CanonicalUserTypeAnnotation
<'tcx
>,
193 self.super_user_type_annotation(index
, ty
);
196 fn visit_region(&mut self,
197 region
: & $
($mutability
)? ty
::Region
<'tcx
>,
199 self.super_region(region
);
202 fn visit_const(&mut self,
203 constant
: & $
($mutability
)?
&'tcx ty
::Const
<'tcx
>,
205 self.super_const(constant
);
208 fn visit_substs(&mut self,
209 substs
: & $
($mutability
)? SubstsRef
<'tcx
>,
211 self.super_substs(substs
);
214 fn visit_local_decl(&mut self,
216 local_decl
: & $
($mutability
)? LocalDecl
<'tcx
>) {
217 self.super_local_decl(local
, local_decl
);
220 fn visit_var_debug_info(&mut self,
221 var_debug_info
: & $
($mutability
)* VarDebugInfo
<'tcx
>) {
222 self.super_var_debug_info(var_debug_info
);
225 fn visit_local(&mut self,
226 _local
: & $
($mutability
)? Local
,
227 _context
: PlaceContext
,
228 _location
: Location
) {
231 fn visit_source_scope(&mut self,
232 scope
: & $
($mutability
)? SourceScope
) {
233 self.super_source_scope(scope
);
236 // The `super_xxx` methods comprise the default behavior and are
237 // not meant to be overridden.
241 body
: &$
($mutability
)? Body
<'tcx
>,
243 let span
= body
.span
;
244 if let Some(yield_ty
) = &$
($mutability
)? body
.yield_ty
{
247 TyContext
::YieldTy(SourceInfo
::outermost(span
))
251 // for best performance, we want to use an iterator rather
252 // than a for-loop, to avoid calling `body::Body::invalidate` for
254 macro_rules
! basic_blocks
{
255 (mut) => (body
.basic_blocks_mut().iter_enumerated_mut());
256 () => (body
.basic_blocks().iter_enumerated());
258 for (bb
, data
) in basic_blocks
!($
($mutability
)?
) {
259 self.visit_basic_block_data(bb
, data
);
262 for scope
in &$
($mutability
)? body
.source_scopes
{
263 self.visit_source_scope_data(scope
);
267 &$
($mutability
)? body
.return_ty(),
268 TyContext
::ReturnTy(SourceInfo
::outermost(body
.span
))
271 for local
in body
.local_decls
.indices() {
272 self.visit_local_decl(local
, & $
($mutability
)? body
.local_decls
[local
]);
275 macro_rules
! type_annotations
{
276 (mut) => (body
.user_type_annotations
.iter_enumerated_mut());
277 () => (body
.user_type_annotations
.iter_enumerated());
280 for (index
, annotation
) in type_annotations
!($
($mutability
)?
) {
281 self.visit_user_type_annotation(
286 for var_debug_info
in &$
($mutability
)? body
.var_debug_info
{
287 self.visit_var_debug_info(var_debug_info
);
290 self.visit_span(&$
($mutability
)? body
.span
);
292 for const_
in &$
($mutability
)? body
.required_consts
{
293 let location
= START_BLOCK
.start_location();
294 self.visit_constant(const_
, location
);
298 fn super_basic_block_data(&mut self,
300 data
: & $
($mutability
)? BasicBlockData
<'tcx
>) {
308 for statement
in statements
{
309 let location
= Location { block: block, statement_index: index }
;
310 self.visit_statement(statement
, location
);
314 if let Some(terminator
) = terminator
{
315 let location
= Location { block: block, statement_index: index }
;
316 self.visit_terminator(terminator
, location
);
320 fn super_source_scope_data(&mut self, scope_data
: & $
($mutability
)? SourceScopeData
) {
321 let SourceScopeData
{
327 self.visit_span(span
);
328 if let Some(parent_scope
) = parent_scope
{
329 self.visit_source_scope(parent_scope
);
333 fn super_statement(&mut self,
334 statement
: & $
($mutability
)? Statement
<'tcx
>,
335 location
: Location
) {
341 self.visit_source_info(source_info
);
343 StatementKind
::Assign(
344 box(ref $
($mutability
)? place
, ref $
($mutability
)? rvalue
)
346 self.visit_assign(place
, rvalue
, location
);
348 StatementKind
::FakeRead(_
, place
) => {
351 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
355 StatementKind
::SetDiscriminant { place, .. }
=> {
358 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
362 StatementKind
::StorageLive(local
) => {
365 PlaceContext
::NonUse(NonUseContext
::StorageLive
),
369 StatementKind
::StorageDead(local
) => {
372 PlaceContext
::NonUse(NonUseContext
::StorageDead
),
376 StatementKind
::LlvmInlineAsm(asm
) => {
377 for output
in & $
($mutability
)? asm
.outputs
[..] {
380 PlaceContext
::MutatingUse(MutatingUseContext
::AsmOutput
),
384 for (span
, input
) in & $
($mutability
)? asm
.inputs
[..] {
385 self.visit_span(span
);
386 self.visit_operand(input
, location
);
389 StatementKind
::Retag(kind
, place
) => {
390 self.visit_retag(kind
, place
, location
);
392 StatementKind
::AscribeUserType(
393 box(ref $
($mutability
)? place
, ref $
($mutability
)? user_ty
),
396 self.visit_ascribe_user_ty(place
, variance
, user_ty
, location
);
398 StatementKind
::Coverage(coverage
) => {
404 StatementKind
::Nop
=> {}
408 fn super_assign(&mut self,
409 place
: &$
($mutability
)? Place
<'tcx
>,
410 rvalue
: &$
($mutability
)? Rvalue
<'tcx
>,
411 location
: Location
) {
414 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
417 self.visit_rvalue(rvalue
, location
);
420 fn super_terminator(&mut self,
421 terminator
: &$
($mutability
)? Terminator
<'tcx
>,
422 location
: Location
) {
423 let Terminator { source_info, kind }
= terminator
;
425 self.visit_source_info(source_info
);
427 TerminatorKind
::Goto { .. }
|
428 TerminatorKind
::Resume
|
429 TerminatorKind
::Abort
|
430 TerminatorKind
::GeneratorDrop
|
431 TerminatorKind
::Unreachable
|
432 TerminatorKind
::FalseEdge { .. }
|
433 TerminatorKind
::FalseUnwind { .. }
=> {
436 TerminatorKind
::Return
=> {
437 // `return` logically moves from the return place `_0`. Note that the place
438 // cannot be changed by any visitor, though.
439 let $
($mutability
)? local
= RETURN_PLACE
;
441 & $
($mutability
)? local
,
442 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Move
),
449 "`MutVisitor` tried to mutate return place of `return` terminator"
453 TerminatorKind
::SwitchInt
{
459 self.visit_operand(discr
, location
);
460 self.visit_ty(switch_ty
, TyContext
::Location(location
));
463 TerminatorKind
::Drop
{
470 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
),
475 TerminatorKind
::DropAndReplace
{
483 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
),
486 self.visit_operand(value
, location
);
489 TerminatorKind
::Call
{
497 self.visit_operand(func
, location
);
499 self.visit_operand(arg
, location
);
501 if let Some((destination
, _
)) = destination
{
504 PlaceContext
::MutatingUse(MutatingUseContext
::Call
),
510 TerminatorKind
::Assert
{
517 self.visit_operand(cond
, location
);
518 self.visit_assert_message(msg
, location
);
521 TerminatorKind
::Yield
{
527 self.visit_operand(value
, location
);
530 PlaceContext
::MutatingUse(MutatingUseContext
::Yield
),
535 TerminatorKind
::InlineAsm
{
544 InlineAsmOperand
::In { value, .. }
545 | InlineAsmOperand
::Const { value }
=> {
546 self.visit_operand(value
, location
);
548 InlineAsmOperand
::Out { place, .. }
=> {
549 if let Some(place
) = place
{
552 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
557 InlineAsmOperand
::InOut { in_value, out_place, .. }
=> {
558 self.visit_operand(in_value
, location
);
559 if let Some(out_place
) = out_place
{
562 PlaceContext
::MutatingUse(MutatingUseContext
::Store
),
567 InlineAsmOperand
::SymFn { value }
=> {
568 self.visit_constant(value
, location
);
570 InlineAsmOperand
::SymStatic { def_id: _ }
=> {}
577 fn super_assert_message(&mut self,
578 msg
: & $
($mutability
)? AssertMessage
<'tcx
>,
579 location
: Location
) {
580 use crate::mir
::AssertKind
::*;
582 BoundsCheck { len, index }
=> {
583 self.visit_operand(len
, location
);
584 self.visit_operand(index
, location
);
586 Overflow(_
, l
, r
) => {
587 self.visit_operand(l
, location
);
588 self.visit_operand(r
, location
);
590 OverflowNeg(op
) | DivisionByZero(op
) | RemainderByZero(op
) => {
591 self.visit_operand(op
, location
);
593 ResumedAfterReturn(_
) | ResumedAfterPanic(_
) => {
599 fn super_rvalue(&mut self,
600 rvalue
: & $
($mutability
)? Rvalue
<'tcx
>,
601 location
: Location
) {
603 Rvalue
::Use(operand
) => {
604 self.visit_operand(operand
, location
);
607 Rvalue
::Repeat(value
, _
) => {
608 self.visit_operand(value
, location
);
611 Rvalue
::ThreadLocalRef(_
) => {}
613 Rvalue
::Ref(r
, bk
, path
) => {
614 self.visit_region(r
, location
);
616 BorrowKind
::Shared
=> PlaceContext
::NonMutatingUse(
617 NonMutatingUseContext
::SharedBorrow
619 BorrowKind
::Shallow
=> PlaceContext
::NonMutatingUse(
620 NonMutatingUseContext
::ShallowBorrow
622 BorrowKind
::Unique
=> PlaceContext
::NonMutatingUse(
623 NonMutatingUseContext
::UniqueBorrow
625 BorrowKind
::Mut { .. }
=>
626 PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
),
628 self.visit_place(path
, ctx
, location
);
631 Rvalue
::AddressOf(m
, path
) => {
633 Mutability
::Mut
=> PlaceContext
::MutatingUse(
634 MutatingUseContext
::AddressOf
636 Mutability
::Not
=> PlaceContext
::NonMutatingUse(
637 NonMutatingUseContext
::AddressOf
640 self.visit_place(path
, ctx
, location
);
643 Rvalue
::Len(path
) => {
646 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
651 Rvalue
::Cast(_cast_kind
, operand
, ty
) => {
652 self.visit_operand(operand
, location
);
653 self.visit_ty(ty
, TyContext
::Location(location
));
656 Rvalue
::BinaryOp(_bin_op
, lhs
, rhs
)
657 | Rvalue
::CheckedBinaryOp(_bin_op
, lhs
, rhs
) => {
658 self.visit_operand(lhs
, location
);
659 self.visit_operand(rhs
, location
);
662 Rvalue
::UnaryOp(_un_op
, op
) => {
663 self.visit_operand(op
, location
);
666 Rvalue
::Discriminant(place
) => {
669 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Inspect
),
674 Rvalue
::NullaryOp(_op
, ty
) => {
675 self.visit_ty(ty
, TyContext
::Location(location
));
678 Rvalue
::Aggregate(kind
, operands
) => {
679 let kind
= &$
($mutability
)?
**kind
;
681 AggregateKind
::Array(ty
) => {
682 self.visit_ty(ty
, TyContext
::Location(location
));
684 AggregateKind
::Tuple
=> {
693 self.visit_substs(substs
, location
);
695 AggregateKind
::Closure(
699 self.visit_substs(closure_substs
, location
);
701 AggregateKind
::Generator(
706 self.visit_substs(generator_substs
, location
);
710 for operand
in operands
{
711 self.visit_operand(operand
, location
);
717 fn super_operand(&mut self,
718 operand
: & $
($mutability
)? Operand
<'tcx
>,
719 location
: Location
) {
721 Operand
::Copy(place
) => {
724 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
728 Operand
::Move(place
) => {
731 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Move
),
735 Operand
::Constant(constant
) => {
736 self.visit_constant(constant
, location
);
741 fn super_ascribe_user_ty(&mut self,
742 place
: & $
($mutability
)? Place
<'tcx
>,
743 _variance
: & $
($mutability
)? ty
::Variance
,
744 user_ty
: & $
($mutability
)? UserTypeProjection
,
745 location
: Location
) {
748 PlaceContext
::NonUse(NonUseContext
::AscribeUserTy
),
751 self.visit_user_type_projection(user_ty
);
754 fn super_coverage(&mut self,
755 _kind
: & $
($mutability
)? Coverage
,
756 _location
: Location
) {
759 fn super_retag(&mut self,
760 _kind
: & $
($mutability
)? RetagKind
,
761 place
: & $
($mutability
)? Place
<'tcx
>,
762 location
: Location
) {
765 PlaceContext
::MutatingUse(MutatingUseContext
::Retag
),
770 fn super_local_decl(&mut self,
772 local_decl
: & $
($mutability
)? LocalDecl
<'tcx
>) {
783 self.visit_ty(ty
, TyContext
::LocalDecl
{
785 source_info
: *source_info
,
787 if let Some(user_ty
) = user_ty
{
788 for (user_ty
, _
) in & $
($mutability
)? user_ty
.contents
{
789 self.visit_user_type_projection(user_ty
);
792 self.visit_source_info(source_info
);
795 fn super_var_debug_info(&mut self,
796 var_debug_info
: & $
($mutability
)? VarDebugInfo
<'tcx
>) {
803 self.visit_source_info(source_info
);
804 let location
= START_BLOCK
.start_location();
807 PlaceContext
::NonUse(NonUseContext
::VarDebugInfo
),
812 fn super_source_scope(&mut self,
813 _scope
: & $
($mutability
)? SourceScope
) {
816 fn super_constant(&mut self,
817 constant
: & $
($mutability
)? Constant
<'tcx
>,
818 location
: Location
) {
825 self.visit_span(span
);
826 drop(user_ty
); // no visit method for this
827 self.visit_const(literal
, location
);
830 fn super_span(&mut self, _span
: & $
($mutability
)? Span
) {
833 fn super_source_info(&mut self, source_info
: & $
($mutability
)? SourceInfo
) {
839 self.visit_span(span
);
840 self.visit_source_scope(scope
);
843 fn super_user_type_projection(
845 _ty
: & $
($mutability
)? UserTypeProjection
,
849 fn super_user_type_annotation(
851 _index
: UserTypeAnnotationIndex
,
852 ty
: & $
($mutability
)? CanonicalUserTypeAnnotation
<'tcx
>,
854 self.visit_span(& $
($mutability
)? ty
.span
);
855 self.visit_ty(& $
($mutability
)? ty
.inferred_ty
, TyContext
::UserTy(ty
.span
));
858 fn super_ty(&mut self, _ty
: $
(& $mutability
)? Ty
<'tcx
>) {
861 fn super_region(&mut self, _region
: & $
($mutability
)? ty
::Region
<'tcx
>) {
864 fn super_const(&mut self, _const
: & $
($mutability
)?
&'tcx ty
::Const
<'tcx
>) {
867 fn super_substs(&mut self, _substs
: & $
($mutability
)? SubstsRef
<'tcx
>) {
870 // Convenience methods
874 body
: &$
($mutability
)? Body
<'tcx
>,
877 macro_rules
! basic_blocks
{
878 (mut) => (body
.basic_blocks_mut());
879 () => (body
.basic_blocks());
881 let basic_block
= & $
($mutability
)? basic_blocks
!($
($mutability
)?
)[location
.block
];
882 if basic_block
.statements
.len() == location
.statement_index
{
883 if let Some(ref $
($mutability
)? terminator
) = basic_block
.terminator
{
884 self.visit_terminator(terminator
, location
)
887 let statement
= & $
($mutability
)?
888 basic_block
.statements
[location
.statement_index
];
889 self.visit_statement(statement
, location
)
896 macro_rules
! visit_place_fns
{
898 fn tcx
<'a
>(&'a
self) -> TyCtxt
<'tcx
>;
902 place
: &mut Place
<'tcx
>,
903 context
: PlaceContext
,
906 self.visit_local(&mut place
.local
, context
, location
);
908 if let Some(new_projection
) = self.process_projection(&place
.projection
, location
) {
909 place
.projection
= self.tcx().intern_place_elems(&new_projection
);
913 fn process_projection(
915 projection
: &'a
[PlaceElem
<'tcx
>],
917 ) -> Option
<Vec
<PlaceElem
<'tcx
>>> {
918 let mut projection
= Cow
::Borrowed(projection
);
920 for i
in 0..projection
.len() {
921 if let Some(&elem
) = projection
.get(i
) {
922 if let Some(elem
) = self.process_projection_elem(elem
, location
) {
923 // This converts the borrowed projection into `Cow::Owned(_)` and returns a
924 // clone of the projection so we can mutate and reintern later.
925 let vec
= projection
.to_mut();
932 Cow
::Borrowed(_
) => None
,
933 Cow
::Owned(vec
) => Some(vec
),
937 fn process_projection_elem(
939 elem
: PlaceElem
<'tcx
>,
941 ) -> Option
<PlaceElem
<'tcx
>> {
943 PlaceElem
::Index(local
) => {
944 let mut new_local
= local
;
947 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
951 if new_local
== local { None }
else { Some(PlaceElem::Index(new_local)) }
954 | PlaceElem
::Field(..)
955 | PlaceElem
::ConstantIndex { .. }
956 | PlaceElem
::Subslice { .. }
957 | PlaceElem
::Downcast(..) => None
,
966 projection
: &[PlaceElem
<'tcx
>],
967 context
: PlaceContext
,
970 self.super_projection(local
, projection
, context
, location
);
973 fn visit_projection_elem(
976 proj_base
: &[PlaceElem
<'tcx
>],
977 elem
: PlaceElem
<'tcx
>,
978 context
: PlaceContext
,
981 self.super_projection_elem(local
, proj_base
, elem
, context
, location
);
984 fn super_place(&mut self, place
: &Place
<'tcx
>, context
: PlaceContext
, location
: Location
) {
985 let mut context
= context
;
987 if !place
.projection
.is_empty() {
988 context
= if context
.is_mutating_use() {
989 PlaceContext
::MutatingUse(MutatingUseContext
::Projection
)
991 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Projection
)
995 self.visit_local(&place
.local
, context
, location
);
997 self.visit_projection(place
.local
, &place
.projection
, context
, location
);
1000 fn super_projection(
1003 projection
: &[PlaceElem
<'tcx
>],
1004 context
: PlaceContext
,
1007 let mut cursor
= projection
;
1008 while let &[ref proj_base @
.., elem
] = cursor
{
1010 self.visit_projection_elem(local
, cursor
, elem
, context
, location
);
1014 fn super_projection_elem(
1017 _proj_base
: &[PlaceElem
<'tcx
>],
1018 elem
: PlaceElem
<'tcx
>,
1019 _context
: PlaceContext
,
1023 ProjectionElem
::Field(_field
, ty
) => {
1024 self.visit_ty(ty
, TyContext
::Location(location
));
1026 ProjectionElem
::Index(local
) => {
1029 PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
),
1033 ProjectionElem
::Deref
1034 | ProjectionElem
::Subslice { from: _, to: _, from_end: _ }
1035 | ProjectionElem
::ConstantIndex { offset: _, min_length: _, from_end: _ }
1036 | ProjectionElem
::Downcast(_
, _
) => {}
1042 make_mir_visitor
!(Visitor
,);
1043 make_mir_visitor
!(MutVisitor
, mut);
1045 pub trait MirVisitable
<'tcx
> {
1046 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>);
1049 impl<'tcx
> MirVisitable
<'tcx
> for Statement
<'tcx
> {
1050 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
1051 visitor
.visit_statement(self, location
)
1055 impl<'tcx
> MirVisitable
<'tcx
> for Terminator
<'tcx
> {
1056 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
1057 visitor
.visit_terminator(self, location
)
1061 impl<'tcx
> MirVisitable
<'tcx
> for Option
<Terminator
<'tcx
>> {
1062 fn apply(&self, location
: Location
, visitor
: &mut dyn Visitor
<'tcx
>) {
1063 visitor
.visit_terminator(self.as_ref().unwrap(), location
)
1067 /// Extra information passed to `visit_ty` and friends to give context
1068 /// about where the type etc appears.
1070 pub enum TyContext
{
1072 /// The index of the local variable we are visiting.
1075 /// The source location where this local variable was declared.
1076 source_info
: SourceInfo
,
1079 /// The inferred type of a user type annotation.
1082 /// The return type of the function.
1083 ReturnTy(SourceInfo
),
1085 YieldTy(SourceInfo
),
1087 /// A type found at some location.
1091 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1092 pub enum NonMutatingUseContext
{
1093 /// Being inspected in some way, like loading a len.
1095 /// Consumed as part of an operand.
1097 /// Consumed as part of an operand.
1105 /// AddressOf for *const pointer.
1107 /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1108 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1116 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1117 pub enum MutatingUseContext
{
1118 /// Appears as LHS of an assignment.
1120 /// Can often be treated as a `Store`, but needs to be separate because
1121 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1122 /// cannot be simplified the way a `Store`-`Store` can be.
1124 /// Destination of a call.
1126 /// Destination of a yield.
1132 /// AddressOf for *mut pointer.
1134 /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1135 /// For example, the projection `x.y` is marked as a mutation in these cases:
1141 /// Retagging, a "Stacked Borrows" shadow state operation
1145 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1146 pub enum NonUseContext
{
1147 /// Starting a storage live range.
1149 /// Ending a storage live range.
1151 /// User type annotation assertions for NLL.
1153 /// The data of an user variable, for debug info.
1157 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1158 pub enum PlaceContext
{
1159 NonMutatingUse(NonMutatingUseContext
),
1160 MutatingUse(MutatingUseContext
),
1161 NonUse(NonUseContext
),
1165 /// Returns `true` if this place context represents a drop.
1166 pub fn is_drop(&self) -> bool
{
1168 PlaceContext
::MutatingUse(MutatingUseContext
::Drop
) => true,
1173 /// Returns `true` if this place context represents a borrow.
1174 pub fn is_borrow(&self) -> bool
{
1176 PlaceContext
::NonMutatingUse(
1177 NonMutatingUseContext
::SharedBorrow
1178 | NonMutatingUseContext
::ShallowBorrow
1179 | NonMutatingUseContext
::UniqueBorrow
,
1181 | PlaceContext
::MutatingUse(MutatingUseContext
::Borrow
) => true,
1186 /// Returns `true` if this place context represents a storage live or storage dead marker.
1187 pub fn is_storage_marker(&self) -> bool
{
1189 PlaceContext
::NonUse(NonUseContext
::StorageLive
| NonUseContext
::StorageDead
) => true,
1194 /// Returns `true` if this place context represents a storage live marker.
1195 pub fn is_storage_live_marker(&self) -> bool
{
1197 PlaceContext
::NonUse(NonUseContext
::StorageLive
) => true,
1202 /// Returns `true` if this place context represents a storage dead marker.
1203 pub fn is_storage_dead_marker(&self) -> bool
{
1205 PlaceContext
::NonUse(NonUseContext
::StorageDead
) => true,
1210 /// Returns `true` if this place context represents a use that potentially changes the value.
1211 pub fn is_mutating_use(&self) -> bool
{
1213 PlaceContext
::MutatingUse(..) => true,
1218 /// Returns `true` if this place context represents a use that does not change the value.
1219 pub fn is_nonmutating_use(&self) -> bool
{
1221 PlaceContext
::NonMutatingUse(..) => true,
1226 /// Returns `true` if this place context represents a use.
1227 pub fn is_use(&self) -> bool
{
1229 PlaceContext
::NonUse(..) => false,
1234 /// Returns `true` if this place context represents an assignment statement.
1235 pub fn is_place_assignment(&self) -> bool
{
1237 PlaceContext
::MutatingUse(
1238 MutatingUseContext
::Store
1239 | MutatingUseContext
::Call
1240 | MutatingUseContext
::AsmOutput
,