1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use hir::def_id::DefId;
12 use ty::subst::Substs;
13 use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
21 // There are two visitors, one for immutable and one for mutable references,
22 // but both are generated by the following macro. The code is written according
23 // to the following conventions:
25 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
26 // - `visit_foo`, by default, calls `super_foo`
27 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
29 // This allows you as a user to override `visit_foo` for types are
30 // interested in, and invoke (within that method) call
31 // `self.super_foo` to get the default behavior. Just as in an OO
32 // language, you should never call `super` methods ordinarily except
33 // in that circumstance.
35 // For the most part, we do not destructure things external to the
36 // MIR, e.g. types, spans, etc, but simply visit them and stop. This
37 // avoids duplication with other visitors like `TypeFoldable`.
41 // The code is written in a very deliberate style intended to minimize
42 // the chance of things being overlooked. You'll notice that we always
43 // use pattern matching to reference fields and we ensure that all
44 // matches are exhaustive.
46 // For example, the `super_basic_block_data` method begins like this:
49 // fn super_basic_block_data(&mut self,
51 // data: & $($mutability)* BasicBlockData<'tcx>) {
52 // let BasicBlockData {
53 // ref $($mutability)* statements,
54 // ref $($mutability)* terminator,
58 // for statement in statements {
59 // self.visit_statement(block, statement);
66 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
67 // rather than writing `data.statements` in the body. This is because if one
68 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
69 // and hence one will (hopefully) invoke the correct visit methods (if any).
71 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
72 // That means you never write `..` to skip over fields, nor do you write `_`
73 // to skip over variants in a `match`.
75 // The only place that `_` is acceptable is to match a field (or
76 // variant argument) that does not require visiting, as in
77 // `is_cleanup` above.
79 macro_rules! make_mir_visitor {
80 ($visitor_trait_name:ident, $($mutability:ident)*) => {
81 pub trait $visitor_trait_name<'tcx> {
82 // Override these, and call `self.super_xxx` to revert back to the
85 fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
89 fn visit_basic_block_data(&mut self,
91 data: & $($mutability)* BasicBlockData<'tcx>) {
92 self.super_basic_block_data(block, data);
95 fn visit_source_scope_data(&mut self,
96 scope_data: & $($mutability)* SourceScopeData) {
97 self.super_source_scope_data(scope_data);
100 fn visit_statement(&mut self,
102 statement: & $($mutability)* Statement<'tcx>,
103 location: Location) {
104 self.super_statement(block, statement, location);
107 fn visit_assign(&mut self,
109 place: & $($mutability)* Place<'tcx>,
110 rvalue: & $($mutability)* Rvalue<'tcx>,
111 location: Location) {
112 self.super_assign(block, place, rvalue, location);
115 fn visit_terminator(&mut self,
117 terminator: & $($mutability)* Terminator<'tcx>,
118 location: Location) {
119 self.super_terminator(block, terminator, location);
122 fn visit_terminator_kind(&mut self,
124 kind: & $($mutability)* TerminatorKind<'tcx>,
125 location: Location) {
126 self.super_terminator_kind(block, kind, location);
129 fn visit_assert_message(&mut self,
130 msg: & $($mutability)* AssertMessage<'tcx>,
131 location: Location) {
132 self.super_assert_message(msg, location);
135 fn visit_rvalue(&mut self,
136 rvalue: & $($mutability)* Rvalue<'tcx>,
137 location: Location) {
138 self.super_rvalue(rvalue, location);
141 fn visit_operand(&mut self,
142 operand: & $($mutability)* Operand<'tcx>,
143 location: Location) {
144 self.super_operand(operand, location);
147 fn visit_ascribe_user_ty(&mut self,
148 place: & $($mutability)* Place<'tcx>,
149 variance: & $($mutability)* ty::Variance,
150 user_ty: & $($mutability)* UserTypeProjection<'tcx>,
151 location: Location) {
152 self.super_ascribe_user_ty(place, variance, user_ty, location);
155 fn visit_retag(&mut self,
156 fn_entry: & $($mutability)* bool,
157 place: & $($mutability)* Place<'tcx>,
158 location: Location) {
159 self.super_retag(fn_entry, place, location);
162 fn visit_place(&mut self,
163 place: & $($mutability)* Place<'tcx>,
164 context: PlaceContext<'tcx>,
165 location: Location) {
166 self.super_place(place, context, location);
169 fn visit_static(&mut self,
170 static_: & $($mutability)* Static<'tcx>,
171 context: PlaceContext<'tcx>,
172 location: Location) {
173 self.super_static(static_, context, location);
176 fn visit_projection(&mut self,
177 place: & $($mutability)* PlaceProjection<'tcx>,
178 context: PlaceContext<'tcx>,
179 location: Location) {
180 self.super_projection(place, context, location);
183 fn visit_projection_elem(&mut self,
184 place: & $($mutability)* PlaceElem<'tcx>,
185 location: Location) {
186 self.super_projection_elem(place, location);
189 fn visit_branch(&mut self,
191 target: BasicBlock) {
192 self.super_branch(source, target);
195 fn visit_constant(&mut self,
196 constant: & $($mutability)* Constant<'tcx>,
197 location: Location) {
198 self.super_constant(constant, location);
201 fn visit_def_id(&mut self,
202 def_id: & $($mutability)* DefId,
204 self.super_def_id(def_id);
207 fn visit_span(&mut self,
208 span: & $($mutability)* Span) {
209 self.super_span(span);
212 fn visit_source_info(&mut self,
213 source_info: & $($mutability)* SourceInfo) {
214 self.super_source_info(source_info);
217 fn visit_ty(&mut self,
218 ty: & $($mutability)* Ty<'tcx>,
223 fn visit_user_type_projection(
225 ty: & $($mutability)* UserTypeProjection<'tcx>,
227 self.super_user_type_projection(ty);
230 fn visit_user_type_annotation(
232 ty: & $($mutability)* UserTypeAnnotation<'tcx>,
234 self.super_user_type_annotation(ty);
237 fn visit_region(&mut self,
238 region: & $($mutability)* ty::Region<'tcx>,
240 self.super_region(region);
243 fn visit_const(&mut self,
244 constant: & $($mutability)* &'tcx ty::Const<'tcx>,
246 self.super_const(constant);
249 fn visit_substs(&mut self,
250 substs: & $($mutability)* &'tcx Substs<'tcx>,
252 self.super_substs(substs);
255 fn visit_closure_substs(&mut self,
256 substs: & $($mutability)* ClosureSubsts<'tcx>,
258 self.super_closure_substs(substs);
261 fn visit_generator_substs(&mut self,
262 substs: & $($mutability)* GeneratorSubsts<'tcx>,
264 self.super_generator_substs(substs);
267 fn visit_local_decl(&mut self,
269 local_decl: & $($mutability)* LocalDecl<'tcx>) {
270 self.super_local_decl(local, local_decl);
273 fn visit_local(&mut self,
274 _local: & $($mutability)* Local,
275 _context: PlaceContext<'tcx>,
276 _location: Location) {
279 fn visit_source_scope(&mut self,
280 scope: & $($mutability)* SourceScope) {
281 self.super_source_scope(scope);
284 // The `super_xxx` methods comprise the default behavior and are
285 // not meant to be overridden.
287 fn super_mir(&mut self,
288 mir: & $($mutability)* Mir<'tcx>) {
289 if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
290 self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
292 scope: OUTERMOST_SOURCE_SCOPE,
296 // for best performance, we want to use an iterator rather
297 // than a for-loop, to avoid calling Mir::invalidate for
299 macro_rules! basic_blocks {
300 (mut) => (mir.basic_blocks_mut().iter_enumerated_mut());
301 () => (mir.basic_blocks().iter_enumerated());
303 for (bb, data) in basic_blocks!($($mutability)*) {
304 self.visit_basic_block_data(bb, data);
307 for scope in &$($mutability)* mir.source_scopes {
308 self.visit_source_scope_data(scope);
311 self.visit_ty(&$($mutability)* mir.return_ty(), TyContext::ReturnTy(SourceInfo {
313 scope: OUTERMOST_SOURCE_SCOPE,
316 for local in mir.local_decls.indices() {
317 self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
320 self.visit_span(&$($mutability)* mir.span);
323 fn super_basic_block_data(&mut self,
325 data: & $($mutability)* BasicBlockData<'tcx>) {
327 ref $($mutability)* statements,
328 ref $($mutability)* terminator,
333 for statement in statements {
334 let location = Location { block: block, statement_index: index };
335 self.visit_statement(block, statement, location);
339 if let Some(ref $($mutability)* terminator) = *terminator {
340 let location = Location { block: block, statement_index: index };
341 self.visit_terminator(block, terminator, location);
345 fn super_source_scope_data(&mut self,
346 scope_data: & $($mutability)* SourceScopeData) {
347 let SourceScopeData {
348 ref $($mutability)* span,
349 ref $($mutability)* parent_scope,
352 self.visit_span(span);
353 if let Some(ref $($mutability)* parent_scope) = *parent_scope {
354 self.visit_source_scope(parent_scope);
358 fn super_statement(&mut self,
360 statement: & $($mutability)* Statement<'tcx>,
361 location: Location) {
363 ref $($mutability)* source_info,
364 ref $($mutability)* kind,
367 self.visit_source_info(source_info);
369 StatementKind::Assign(ref $($mutability)* place,
370 ref $($mutability)* rvalue) => {
371 self.visit_assign(block, place, rvalue, location);
373 StatementKind::FakeRead(_, ref $($mutability)* place) => {
376 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
380 StatementKind::EndRegion(_) => {}
381 StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
384 PlaceContext::MutatingUse(MutatingUseContext::Store),
388 StatementKind::EscapeToRaw(ref $($mutability)* op) => {
389 self.visit_operand(op, location);
391 StatementKind::StorageLive(ref $($mutability)* local) => {
394 PlaceContext::NonUse(NonUseContext::StorageLive),
398 StatementKind::StorageDead(ref $($mutability)* local) => {
401 PlaceContext::NonUse(NonUseContext::StorageDead),
405 StatementKind::InlineAsm { ref $($mutability)* outputs,
406 ref $($mutability)* inputs,
408 for output in & $($mutability)* outputs[..] {
411 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
415 for (span, input) in & $($mutability)* inputs[..] {
416 self.visit_span(span);
417 self.visit_operand(input, location);
420 StatementKind::Retag { ref $($mutability)* fn_entry,
421 ref $($mutability)* place } => {
422 self.visit_retag(fn_entry, place, location);
424 StatementKind::AscribeUserType(
425 ref $($mutability)* place,
426 ref $($mutability)* variance,
427 ref $($mutability)* user_ty,
429 self.visit_ascribe_user_ty(place, variance, user_ty, location);
431 StatementKind::Nop => {}
435 fn super_assign(&mut self,
437 place: &$($mutability)* Place<'tcx>,
438 rvalue: &$($mutability)* Rvalue<'tcx>,
439 location: Location) {
442 PlaceContext::MutatingUse(MutatingUseContext::Store),
445 self.visit_rvalue(rvalue, location);
448 fn super_terminator(&mut self,
450 terminator: &$($mutability)* Terminator<'tcx>,
451 location: Location) {
453 ref $($mutability)* source_info,
454 ref $($mutability)* kind,
457 self.visit_source_info(source_info);
458 self.visit_terminator_kind(block, kind, location);
461 fn super_terminator_kind(&mut self,
463 kind: & $($mutability)* TerminatorKind<'tcx>,
464 source_location: Location) {
466 TerminatorKind::Goto { target } => {
467 self.visit_branch(block, target);
470 TerminatorKind::SwitchInt { ref $($mutability)* discr,
471 ref $($mutability)* switch_ty,
474 self.visit_operand(discr, source_location);
475 self.visit_ty(switch_ty, TyContext::Location(source_location));
476 for &target in targets {
477 self.visit_branch(block, target);
481 TerminatorKind::Resume |
482 TerminatorKind::Abort |
483 TerminatorKind::Return |
484 TerminatorKind::GeneratorDrop |
485 TerminatorKind::Unreachable => {
488 TerminatorKind::Drop { ref $($mutability)* location,
493 PlaceContext::MutatingUse(MutatingUseContext::Drop),
496 self.visit_branch(block, target);
497 unwind.map(|t| self.visit_branch(block, t));
500 TerminatorKind::DropAndReplace { ref $($mutability)* location,
501 ref $($mutability)* value,
506 PlaceContext::MutatingUse(MutatingUseContext::Drop),
509 self.visit_operand(value, source_location);
510 self.visit_branch(block, target);
511 unwind.map(|t| self.visit_branch(block, t));
514 TerminatorKind::Call { ref $($mutability)* func,
515 ref $($mutability)* args,
516 ref $($mutability)* destination,
518 from_hir_call: _, } => {
519 self.visit_operand(func, source_location);
521 self.visit_operand(arg, source_location);
523 if let Some((ref $($mutability)* destination, target)) = *destination {
526 PlaceContext::MutatingUse(MutatingUseContext::Call),
529 self.visit_branch(block, target);
531 cleanup.map(|t| self.visit_branch(block, t));
534 TerminatorKind::Assert { ref $($mutability)* cond,
536 ref $($mutability)* msg,
539 self.visit_operand(cond, source_location);
540 self.visit_assert_message(msg, source_location);
541 self.visit_branch(block, target);
542 cleanup.map(|t| self.visit_branch(block, t));
545 TerminatorKind::Yield { ref $($mutability)* value,
548 self.visit_operand(value, source_location);
549 self.visit_branch(block, resume);
550 drop.map(|t| self.visit_branch(block, t));
553 TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => {
554 self.visit_branch(block, real_target);
555 for target in imaginary_targets {
556 self.visit_branch(block, *target);
560 TerminatorKind::FalseUnwind { real_target, unwind } => {
561 self.visit_branch(block, real_target);
562 if let Some(unwind) = unwind {
563 self.visit_branch(block, unwind);
569 fn super_assert_message(&mut self,
570 msg: & $($mutability)* AssertMessage<'tcx>,
571 location: Location) {
572 use mir::interpret::EvalErrorKind::*;
574 ref $($mutability)* len,
575 ref $($mutability)* index
577 self.visit_operand(len, location);
578 self.visit_operand(index, location);
582 fn super_rvalue(&mut self,
583 rvalue: & $($mutability)* Rvalue<'tcx>,
584 location: Location) {
586 Rvalue::Use(ref $($mutability)* operand) => {
587 self.visit_operand(operand, location);
590 Rvalue::Repeat(ref $($mutability)* value, _) => {
591 self.visit_operand(value, location);
594 Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
595 self.visit_region(r, location);
597 BorrowKind::Shared => PlaceContext::NonMutatingUse(
598 NonMutatingUseContext::SharedBorrow(*r)
600 BorrowKind::Shallow => PlaceContext::NonMutatingUse(
601 NonMutatingUseContext::ShallowBorrow(*r)
603 BorrowKind::Unique => PlaceContext::NonMutatingUse(
604 NonMutatingUseContext::UniqueBorrow(*r)
606 BorrowKind::Mut { .. } =>
607 PlaceContext::MutatingUse(MutatingUseContext::Borrow(*r)),
609 self.visit_place(path, ctx, location);
612 Rvalue::Len(ref $($mutability)* path) => {
615 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
620 Rvalue::Cast(_cast_kind,
621 ref $($mutability)* operand,
622 ref $($mutability)* ty) => {
623 self.visit_operand(operand, location);
624 self.visit_ty(ty, TyContext::Location(location));
627 Rvalue::BinaryOp(_bin_op,
628 ref $($mutability)* lhs,
629 ref $($mutability)* rhs) |
630 Rvalue::CheckedBinaryOp(_bin_op,
631 ref $($mutability)* lhs,
632 ref $($mutability)* rhs) => {
633 self.visit_operand(lhs, location);
634 self.visit_operand(rhs, location);
637 Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
638 self.visit_operand(op, location);
641 Rvalue::Discriminant(ref $($mutability)* place) => {
644 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
649 Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
650 self.visit_ty(ty, TyContext::Location(location));
653 Rvalue::Aggregate(ref $($mutability)* kind,
654 ref $($mutability)* operands) => {
655 let kind = &$($mutability)* **kind;
657 AggregateKind::Array(ref $($mutability)* ty) => {
658 self.visit_ty(ty, TyContext::Location(location));
660 AggregateKind::Tuple => {
662 AggregateKind::Adt(_adt_def,
664 ref $($mutability)* substs,
666 _active_field_index) => {
667 self.visit_substs(substs, location);
669 AggregateKind::Closure(ref $($mutability)* def_id,
670 ref $($mutability)* closure_substs) => {
671 self.visit_def_id(def_id, location);
672 self.visit_closure_substs(closure_substs, location);
674 AggregateKind::Generator(ref $($mutability)* def_id,
675 ref $($mutability)* generator_substs,
677 self.visit_def_id(def_id, location);
678 self.visit_generator_substs(generator_substs, location);
682 for operand in operands {
683 self.visit_operand(operand, location);
689 fn super_operand(&mut self,
690 operand: & $($mutability)* Operand<'tcx>,
691 location: Location) {
693 Operand::Copy(ref $($mutability)* place) => {
696 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
700 Operand::Move(ref $($mutability)* place) => {
703 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
707 Operand::Constant(ref $($mutability)* constant) => {
708 self.visit_constant(constant, location);
713 fn super_ascribe_user_ty(&mut self,
714 place: & $($mutability)* Place<'tcx>,
715 _variance: & $($mutability)* ty::Variance,
716 user_ty: & $($mutability)* UserTypeProjection<'tcx>,
717 location: Location) {
720 PlaceContext::NonUse(NonUseContext::AscribeUserTy),
723 self.visit_user_type_projection(user_ty);
726 fn super_retag(&mut self,
727 _fn_entry: & $($mutability)* bool,
728 place: & $($mutability)* Place<'tcx>,
729 location: Location) {
732 PlaceContext::MutatingUse(MutatingUseContext::Retag),
737 fn super_place(&mut self,
738 place: & $($mutability)* Place<'tcx>,
739 context: PlaceContext<'tcx>,
740 location: Location) {
742 Place::Local(ref $($mutability)* local) => {
743 self.visit_local(local, context, location);
745 Place::Static(ref $($mutability)* static_) => {
746 self.visit_static(static_, context, location);
748 Place::Promoted(ref $($mutability)* promoted) => {
749 self.visit_ty(& $($mutability)* promoted.1, TyContext::Location(location));
751 Place::Projection(ref $($mutability)* proj) => {
752 self.visit_projection(proj, context, location);
757 fn super_static(&mut self,
758 static_: & $($mutability)* Static<'tcx>,
759 _context: PlaceContext<'tcx>,
760 location: Location) {
762 ref $($mutability)* def_id,
763 ref $($mutability)* ty,
765 self.visit_def_id(def_id, location);
766 self.visit_ty(ty, TyContext::Location(location));
769 fn super_projection(&mut self,
770 proj: & $($mutability)* PlaceProjection<'tcx>,
771 context: PlaceContext<'tcx>,
772 location: Location) {
774 ref $($mutability)* base,
775 ref $($mutability)* elem,
777 let context = if context.is_mutating_use() {
778 PlaceContext::MutatingUse(MutatingUseContext::Projection)
780 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
782 self.visit_place(base, context, location);
783 self.visit_projection_elem(elem, location);
786 fn super_projection_elem(&mut self,
787 proj: & $($mutability)* PlaceElem<'tcx>,
788 location: Location) {
790 ProjectionElem::Deref => {
792 ProjectionElem::Subslice { from: _, to: _ } => {
794 ProjectionElem::Field(_field, ref $($mutability)* ty) => {
795 self.visit_ty(ty, TyContext::Location(location));
797 ProjectionElem::Index(ref $($mutability)* local) => {
800 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
804 ProjectionElem::ConstantIndex { offset: _,
808 ProjectionElem::Downcast(_adt_def, _variant_index) => {
813 fn super_local_decl(&mut self,
815 local_decl: & $($mutability)* LocalDecl<'tcx>) {
818 ref $($mutability)* ty,
819 ref $($mutability)* user_ty,
821 ref $($mutability)* source_info,
822 ref $($mutability)* visibility_scope,
828 self.visit_ty(ty, TyContext::LocalDecl {
830 source_info: *source_info,
832 for (user_ty, _) in & $($mutability)* user_ty.contents {
833 self.visit_user_type_projection(user_ty);
835 self.visit_source_info(source_info);
836 self.visit_source_scope(visibility_scope);
839 fn super_source_scope(&mut self,
840 _scope: & $($mutability)* SourceScope) {
843 fn super_branch(&mut self,
845 _target: BasicBlock) {
848 fn super_constant(&mut self,
849 constant: & $($mutability)* Constant<'tcx>,
850 location: Location) {
852 ref $($mutability)* span,
853 ref $($mutability)* ty,
854 ref $($mutability)* user_ty,
855 ref $($mutability)* literal,
858 self.visit_span(span);
859 self.visit_ty(ty, TyContext::Location(location));
860 drop(user_ty); // no visit method for this
861 self.visit_const(literal, location);
864 fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
867 fn super_span(&mut self, _span: & $($mutability)* Span) {
870 fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
872 ref $($mutability)* span,
873 ref $($mutability)* scope,
876 self.visit_span(span);
877 self.visit_source_scope(scope);
880 fn super_user_type_projection(
882 ty: & $($mutability)* UserTypeProjection<'tcx>,
884 let UserTypeProjection {
885 ref $($mutability)* base,
886 projs: _, // Note: Does not visit projection elems!
888 self.visit_user_type_annotation(base);
891 fn super_user_type_annotation(
893 _ty: & $($mutability)* UserTypeAnnotation<'tcx>,
897 fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
900 fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
903 fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) {
906 fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
909 fn super_generator_substs(&mut self,
910 _substs: & $($mutability)* GeneratorSubsts<'tcx>) {
913 fn super_closure_substs(&mut self,
914 _substs: & $($mutability)* ClosureSubsts<'tcx>) {
917 // Convenience methods
919 fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
920 let basic_block = & $($mutability)* mir[location.block];
921 if basic_block.statements.len() == location.statement_index {
922 if let Some(ref $($mutability)* terminator) = basic_block.terminator {
923 self.visit_terminator(location.block, terminator, location)
926 let statement = & $($mutability)*
927 basic_block.statements[location.statement_index];
928 self.visit_statement(location.block, statement, location)
935 make_mir_visitor!(Visitor,);
936 make_mir_visitor!(MutVisitor,mut);
938 pub trait MirVisitable<'tcx> {
939 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
942 impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
943 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
945 visitor.visit_statement(location.block, self, location)
949 impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
950 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
952 visitor.visit_terminator(location.block, self, location)
956 impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
957 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
959 visitor.visit_terminator(location.block, self.as_ref().unwrap(), location)
963 /// Extra information passed to `visit_ty` and friends to give context
964 /// about where the type etc appears.
965 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
968 /// The index of the local variable we are visiting.
971 /// The source location where this local variable was declared.
972 source_info: SourceInfo,
975 /// The return type of the function.
976 ReturnTy(SourceInfo),
980 /// A type found at some location.
984 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
985 pub enum NonMutatingUseContext<'tcx> {
986 /// Being inspected in some way, like loading a len.
988 /// Consumed as part of an operand.
990 /// Consumed as part of an operand.
993 SharedBorrow(Region<'tcx>),
995 ShallowBorrow(Region<'tcx>),
997 UniqueBorrow(Region<'tcx>),
998 /// Used as base for another place, e.g. `x` in `x.y`. Will not mutate the place.
999 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1007 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1008 pub enum MutatingUseContext<'tcx> {
1009 /// Appears as LHS of an assignment.
1011 /// Can often be treated as a `Store`, but needs to be separate because
1012 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1013 /// cannot be simplified the way a `Store`-`Store` can be.
1015 /// Destination of a call.
1020 Borrow(Region<'tcx>),
1021 /// Used as base for another place, e.g. `x` in `x.y`. Could potentially mutate the place.
1022 /// For example, the projection `x.y` is marked as a mutation in these cases:
1028 /// Retagging, a "Stacked Borrows" shadow state operation
1032 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1033 pub enum NonUseContext {
1034 /// Starting a storage live range.
1036 /// Ending a storage live range.
1038 /// User type annotation assertions for NLL.
1042 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1043 pub enum PlaceContext<'tcx> {
1044 NonMutatingUse(NonMutatingUseContext<'tcx>),
1045 MutatingUse(MutatingUseContext<'tcx>),
1046 NonUse(NonUseContext),
1049 impl<'tcx> PlaceContext<'tcx> {
1050 /// Returns `true` if this place context represents a drop.
1051 pub fn is_drop(&self) -> bool {
1053 PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
1058 /// Returns `true` if this place context represents a borrow.
1059 pub fn is_borrow(&self) -> bool {
1061 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
1062 PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
1063 PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
1064 PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) => true,
1069 /// Returns `true` if this place context represents a storage live or storage dead marker.
1070 pub fn is_storage_marker(&self) -> bool {
1072 PlaceContext::NonUse(NonUseContext::StorageLive) |
1073 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1078 /// Returns `true` if this place context represents a storage live marker.
1079 pub fn is_storage_live_marker(&self) -> bool {
1081 PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1086 /// Returns `true` if this place context represents a storage dead marker.
1087 pub fn is_storage_dead_marker(&self) -> bool {
1089 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1094 /// Returns `true` if this place context represents a use that potentially changes the value.
1095 pub fn is_mutating_use(&self) -> bool {
1097 PlaceContext::MutatingUse(..) => true,
1102 /// Returns `true` if this place context represents a use that does not change the value.
1103 pub fn is_nonmutating_use(&self) -> bool {
1105 PlaceContext::NonMutatingUse(..) => true,
1110 /// Returns `true` if this place context represents a use.
1111 pub fn is_use(&self) -> bool {
1113 PlaceContext::NonUse(..) => false,
1118 /// Returns `true` if this place context represents an assignment statement.
1119 pub fn is_place_assignment(&self) -> bool {
1121 PlaceContext::MutatingUse(MutatingUseContext::Store) |
1122 PlaceContext::MutatingUse(MutatingUseContext::Call) |
1123 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true,