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 two_phase: & $($mutability)* bool,
158 place: & $($mutability)* Place<'tcx>,
159 location: Location) {
160 self.super_retag(fn_entry, two_phase, place, location);
163 fn visit_place(&mut self,
164 place: & $($mutability)* Place<'tcx>,
165 context: PlaceContext<'tcx>,
166 location: Location) {
167 self.super_place(place, context, location);
170 fn visit_static(&mut self,
171 static_: & $($mutability)* Static<'tcx>,
172 context: PlaceContext<'tcx>,
173 location: Location) {
174 self.super_static(static_, context, location);
177 fn visit_projection(&mut self,
178 place: & $($mutability)* PlaceProjection<'tcx>,
179 context: PlaceContext<'tcx>,
180 location: Location) {
181 self.super_projection(place, context, location);
184 fn visit_projection_elem(&mut self,
185 place: & $($mutability)* PlaceElem<'tcx>,
186 location: Location) {
187 self.super_projection_elem(place, location);
190 fn visit_branch(&mut self,
192 target: BasicBlock) {
193 self.super_branch(source, target);
196 fn visit_constant(&mut self,
197 constant: & $($mutability)* Constant<'tcx>,
198 location: Location) {
199 self.super_constant(constant, location);
202 fn visit_def_id(&mut self,
203 def_id: & $($mutability)* DefId,
205 self.super_def_id(def_id);
208 fn visit_span(&mut self,
209 span: & $($mutability)* Span) {
210 self.super_span(span);
213 fn visit_source_info(&mut self,
214 source_info: & $($mutability)* SourceInfo) {
215 self.super_source_info(source_info);
218 fn visit_ty(&mut self,
219 ty: & $($mutability)* Ty<'tcx>,
224 fn visit_user_type_projection(
226 ty: & $($mutability)* UserTypeProjection<'tcx>,
228 self.super_user_type_projection(ty);
231 fn visit_user_type_annotation(
233 ty: & $($mutability)* UserTypeAnnotation<'tcx>,
235 self.super_user_type_annotation(ty);
238 fn visit_region(&mut self,
239 region: & $($mutability)* ty::Region<'tcx>,
241 self.super_region(region);
244 fn visit_const(&mut self,
245 constant: & $($mutability)* &'tcx ty::Const<'tcx>,
247 self.super_const(constant);
250 fn visit_substs(&mut self,
251 substs: & $($mutability)* &'tcx Substs<'tcx>,
253 self.super_substs(substs);
256 fn visit_closure_substs(&mut self,
257 substs: & $($mutability)* ClosureSubsts<'tcx>,
259 self.super_closure_substs(substs);
262 fn visit_generator_substs(&mut self,
263 substs: & $($mutability)* GeneratorSubsts<'tcx>,
265 self.super_generator_substs(substs);
268 fn visit_local_decl(&mut self,
270 local_decl: & $($mutability)* LocalDecl<'tcx>) {
271 self.super_local_decl(local, local_decl);
274 fn visit_local(&mut self,
275 _local: & $($mutability)* Local,
276 _context: PlaceContext<'tcx>,
277 _location: Location) {
280 fn visit_source_scope(&mut self,
281 scope: & $($mutability)* SourceScope) {
282 self.super_source_scope(scope);
285 // The `super_xxx` methods comprise the default behavior and are
286 // not meant to be overridden.
288 fn super_mir(&mut self,
289 mir: & $($mutability)* Mir<'tcx>) {
290 if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
291 self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
293 scope: OUTERMOST_SOURCE_SCOPE,
297 // for best performance, we want to use an iterator rather
298 // than a for-loop, to avoid calling Mir::invalidate for
300 macro_rules! basic_blocks {
301 (mut) => (mir.basic_blocks_mut().iter_enumerated_mut());
302 () => (mir.basic_blocks().iter_enumerated());
304 for (bb, data) in basic_blocks!($($mutability)*) {
305 self.visit_basic_block_data(bb, data);
308 for scope in &$($mutability)* mir.source_scopes {
309 self.visit_source_scope_data(scope);
312 self.visit_ty(&$($mutability)* mir.return_ty(), TyContext::ReturnTy(SourceInfo {
314 scope: OUTERMOST_SOURCE_SCOPE,
317 for local in mir.local_decls.indices() {
318 self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
321 self.visit_span(&$($mutability)* mir.span);
324 fn super_basic_block_data(&mut self,
326 data: & $($mutability)* BasicBlockData<'tcx>) {
328 ref $($mutability)* statements,
329 ref $($mutability)* terminator,
334 for statement in statements {
335 let location = Location { block: block, statement_index: index };
336 self.visit_statement(block, statement, location);
340 if let Some(ref $($mutability)* terminator) = *terminator {
341 let location = Location { block: block, statement_index: index };
342 self.visit_terminator(block, terminator, location);
346 fn super_source_scope_data(&mut self,
347 scope_data: & $($mutability)* SourceScopeData) {
348 let SourceScopeData {
349 ref $($mutability)* span,
350 ref $($mutability)* parent_scope,
353 self.visit_span(span);
354 if let Some(ref $($mutability)* parent_scope) = *parent_scope {
355 self.visit_source_scope(parent_scope);
359 fn super_statement(&mut self,
361 statement: & $($mutability)* Statement<'tcx>,
362 location: Location) {
364 ref $($mutability)* source_info,
365 ref $($mutability)* kind,
368 self.visit_source_info(source_info);
370 StatementKind::Assign(ref $($mutability)* place,
371 ref $($mutability)* rvalue) => {
372 self.visit_assign(block, place, rvalue, location);
374 StatementKind::FakeRead(_, ref $($mutability)* place) => {
377 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
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)* two_phase,
422 ref $($mutability)* place } => {
423 self.visit_retag(fn_entry, two_phase, place, location);
425 StatementKind::AscribeUserType(
426 ref $($mutability)* place,
427 ref $($mutability)* variance,
428 ref $($mutability)* user_ty,
430 self.visit_ascribe_user_ty(place, variance, user_ty, location);
432 StatementKind::Nop => {}
436 fn super_assign(&mut self,
438 place: &$($mutability)* Place<'tcx>,
439 rvalue: &$($mutability)* Rvalue<'tcx>,
440 location: Location) {
443 PlaceContext::MutatingUse(MutatingUseContext::Store),
446 self.visit_rvalue(rvalue, location);
449 fn super_terminator(&mut self,
451 terminator: &$($mutability)* Terminator<'tcx>,
452 location: Location) {
454 ref $($mutability)* source_info,
455 ref $($mutability)* kind,
458 self.visit_source_info(source_info);
459 self.visit_terminator_kind(block, kind, location);
462 fn super_terminator_kind(&mut self,
464 kind: & $($mutability)* TerminatorKind<'tcx>,
465 source_location: Location) {
467 TerminatorKind::Goto { target } => {
468 self.visit_branch(block, target);
471 TerminatorKind::SwitchInt { ref $($mutability)* discr,
472 ref $($mutability)* switch_ty,
475 self.visit_operand(discr, source_location);
476 self.visit_ty(switch_ty, TyContext::Location(source_location));
477 for &target in targets {
478 self.visit_branch(block, target);
482 TerminatorKind::Resume |
483 TerminatorKind::Abort |
484 TerminatorKind::Return |
485 TerminatorKind::GeneratorDrop |
486 TerminatorKind::Unreachable => {
489 TerminatorKind::Drop { ref $($mutability)* location,
494 PlaceContext::MutatingUse(MutatingUseContext::Drop),
497 self.visit_branch(block, target);
498 unwind.map(|t| self.visit_branch(block, t));
501 TerminatorKind::DropAndReplace { ref $($mutability)* location,
502 ref $($mutability)* value,
507 PlaceContext::MutatingUse(MutatingUseContext::Drop),
510 self.visit_operand(value, source_location);
511 self.visit_branch(block, target);
512 unwind.map(|t| self.visit_branch(block, t));
515 TerminatorKind::Call { ref $($mutability)* func,
516 ref $($mutability)* args,
517 ref $($mutability)* destination,
519 from_hir_call: _, } => {
520 self.visit_operand(func, source_location);
522 self.visit_operand(arg, source_location);
524 if let Some((ref $($mutability)* destination, target)) = *destination {
527 PlaceContext::MutatingUse(MutatingUseContext::Call),
530 self.visit_branch(block, target);
532 cleanup.map(|t| self.visit_branch(block, t));
535 TerminatorKind::Assert { ref $($mutability)* cond,
537 ref $($mutability)* msg,
540 self.visit_operand(cond, source_location);
541 self.visit_assert_message(msg, source_location);
542 self.visit_branch(block, target);
543 cleanup.map(|t| self.visit_branch(block, t));
546 TerminatorKind::Yield { ref $($mutability)* value,
549 self.visit_operand(value, source_location);
550 self.visit_branch(block, resume);
551 drop.map(|t| self.visit_branch(block, t));
554 TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => {
555 self.visit_branch(block, real_target);
556 for target in imaginary_targets {
557 self.visit_branch(block, *target);
561 TerminatorKind::FalseUnwind { real_target, unwind } => {
562 self.visit_branch(block, real_target);
563 if let Some(unwind) = unwind {
564 self.visit_branch(block, unwind);
570 fn super_assert_message(&mut self,
571 msg: & $($mutability)* AssertMessage<'tcx>,
572 location: Location) {
573 use mir::interpret::EvalErrorKind::*;
575 ref $($mutability)* len,
576 ref $($mutability)* index
578 self.visit_operand(len, location);
579 self.visit_operand(index, location);
583 fn super_rvalue(&mut self,
584 rvalue: & $($mutability)* Rvalue<'tcx>,
585 location: Location) {
587 Rvalue::Use(ref $($mutability)* operand) => {
588 self.visit_operand(operand, location);
591 Rvalue::Repeat(ref $($mutability)* value, _) => {
592 self.visit_operand(value, location);
595 Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
596 self.visit_region(r, location);
598 BorrowKind::Shared => PlaceContext::NonMutatingUse(
599 NonMutatingUseContext::SharedBorrow(*r)
601 BorrowKind::Shallow => PlaceContext::NonMutatingUse(
602 NonMutatingUseContext::ShallowBorrow(*r)
604 BorrowKind::Unique => PlaceContext::NonMutatingUse(
605 NonMutatingUseContext::UniqueBorrow(*r)
607 BorrowKind::Mut { .. } =>
608 PlaceContext::MutatingUse(MutatingUseContext::Borrow(*r)),
610 self.visit_place(path, ctx, location);
613 Rvalue::Len(ref $($mutability)* path) => {
616 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
621 Rvalue::Cast(_cast_kind,
622 ref $($mutability)* operand,
623 ref $($mutability)* ty) => {
624 self.visit_operand(operand, location);
625 self.visit_ty(ty, TyContext::Location(location));
628 Rvalue::BinaryOp(_bin_op,
629 ref $($mutability)* lhs,
630 ref $($mutability)* rhs) |
631 Rvalue::CheckedBinaryOp(_bin_op,
632 ref $($mutability)* lhs,
633 ref $($mutability)* rhs) => {
634 self.visit_operand(lhs, location);
635 self.visit_operand(rhs, location);
638 Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
639 self.visit_operand(op, location);
642 Rvalue::Discriminant(ref $($mutability)* place) => {
645 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
650 Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
651 self.visit_ty(ty, TyContext::Location(location));
654 Rvalue::Aggregate(ref $($mutability)* kind,
655 ref $($mutability)* operands) => {
656 let kind = &$($mutability)* **kind;
658 AggregateKind::Array(ref $($mutability)* ty) => {
659 self.visit_ty(ty, TyContext::Location(location));
661 AggregateKind::Tuple => {
663 AggregateKind::Adt(_adt_def,
665 ref $($mutability)* substs,
667 _active_field_index) => {
668 self.visit_substs(substs, location);
670 AggregateKind::Closure(ref $($mutability)* def_id,
671 ref $($mutability)* closure_substs) => {
672 self.visit_def_id(def_id, location);
673 self.visit_closure_substs(closure_substs, location);
675 AggregateKind::Generator(ref $($mutability)* def_id,
676 ref $($mutability)* generator_substs,
678 self.visit_def_id(def_id, location);
679 self.visit_generator_substs(generator_substs, location);
683 for operand in operands {
684 self.visit_operand(operand, location);
690 fn super_operand(&mut self,
691 operand: & $($mutability)* Operand<'tcx>,
692 location: Location) {
694 Operand::Copy(ref $($mutability)* place) => {
697 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
701 Operand::Move(ref $($mutability)* place) => {
704 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
708 Operand::Constant(ref $($mutability)* constant) => {
709 self.visit_constant(constant, location);
714 fn super_ascribe_user_ty(&mut self,
715 place: & $($mutability)* Place<'tcx>,
716 _variance: & $($mutability)* ty::Variance,
717 user_ty: & $($mutability)* UserTypeProjection<'tcx>,
718 location: Location) {
721 PlaceContext::NonUse(NonUseContext::AscribeUserTy),
724 self.visit_user_type_projection(user_ty);
727 fn super_retag(&mut self,
728 _fn_entry: & $($mutability)* bool,
729 _two_phase: & $($mutability)* bool,
730 place: & $($mutability)* Place<'tcx>,
731 location: Location) {
734 PlaceContext::MutatingUse(MutatingUseContext::Retag),
739 fn super_place(&mut self,
740 place: & $($mutability)* Place<'tcx>,
741 context: PlaceContext<'tcx>,
742 location: Location) {
744 Place::Local(ref $($mutability)* local) => {
745 self.visit_local(local, context, location);
747 Place::Static(ref $($mutability)* static_) => {
748 self.visit_static(static_, context, location);
750 Place::Promoted(ref $($mutability)* promoted) => {
751 self.visit_ty(& $($mutability)* promoted.1, TyContext::Location(location));
753 Place::Projection(ref $($mutability)* proj) => {
754 self.visit_projection(proj, context, location);
759 fn super_static(&mut self,
760 static_: & $($mutability)* Static<'tcx>,
761 _context: PlaceContext<'tcx>,
762 location: Location) {
764 ref $($mutability)* def_id,
765 ref $($mutability)* ty,
767 self.visit_def_id(def_id, location);
768 self.visit_ty(ty, TyContext::Location(location));
771 fn super_projection(&mut self,
772 proj: & $($mutability)* PlaceProjection<'tcx>,
773 context: PlaceContext<'tcx>,
774 location: Location) {
776 ref $($mutability)* base,
777 ref $($mutability)* elem,
779 let context = if context.is_mutating_use() {
780 PlaceContext::MutatingUse(MutatingUseContext::Projection)
782 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
784 self.visit_place(base, context, location);
785 self.visit_projection_elem(elem, location);
788 fn super_projection_elem(&mut self,
789 proj: & $($mutability)* PlaceElem<'tcx>,
790 location: Location) {
792 ProjectionElem::Deref => {
794 ProjectionElem::Subslice { from: _, to: _ } => {
796 ProjectionElem::Field(_field, ref $($mutability)* ty) => {
797 self.visit_ty(ty, TyContext::Location(location));
799 ProjectionElem::Index(ref $($mutability)* local) => {
802 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
806 ProjectionElem::ConstantIndex { offset: _,
810 ProjectionElem::Downcast(_adt_def, _variant_index) => {
815 fn super_local_decl(&mut self,
817 local_decl: & $($mutability)* LocalDecl<'tcx>) {
820 ref $($mutability)* ty,
821 ref $($mutability)* user_ty,
823 ref $($mutability)* source_info,
824 ref $($mutability)* visibility_scope,
830 self.visit_ty(ty, TyContext::LocalDecl {
832 source_info: *source_info,
834 for (user_ty, _) in & $($mutability)* user_ty.contents {
835 self.visit_user_type_projection(user_ty);
837 self.visit_source_info(source_info);
838 self.visit_source_scope(visibility_scope);
841 fn super_source_scope(&mut self,
842 _scope: & $($mutability)* SourceScope) {
845 fn super_branch(&mut self,
847 _target: BasicBlock) {
850 fn super_constant(&mut self,
851 constant: & $($mutability)* Constant<'tcx>,
852 location: Location) {
854 ref $($mutability)* span,
855 ref $($mutability)* ty,
856 ref $($mutability)* user_ty,
857 ref $($mutability)* literal,
860 self.visit_span(span);
861 self.visit_ty(ty, TyContext::Location(location));
862 drop(user_ty); // no visit method for this
863 self.visit_const(literal, location);
866 fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
869 fn super_span(&mut self, _span: & $($mutability)* Span) {
872 fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
874 ref $($mutability)* span,
875 ref $($mutability)* scope,
878 self.visit_span(span);
879 self.visit_source_scope(scope);
882 fn super_user_type_projection(
884 ty: & $($mutability)* UserTypeProjection<'tcx>,
886 let UserTypeProjection {
887 ref $($mutability)* base,
888 projs: _, // Note: Does not visit projection elems!
890 self.visit_user_type_annotation(base);
893 fn super_user_type_annotation(
895 _ty: & $($mutability)* UserTypeAnnotation<'tcx>,
899 fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
902 fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
905 fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) {
908 fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
911 fn super_generator_substs(&mut self,
912 _substs: & $($mutability)* GeneratorSubsts<'tcx>) {
915 fn super_closure_substs(&mut self,
916 _substs: & $($mutability)* ClosureSubsts<'tcx>) {
919 // Convenience methods
921 fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
922 let basic_block = & $($mutability)* mir[location.block];
923 if basic_block.statements.len() == location.statement_index {
924 if let Some(ref $($mutability)* terminator) = basic_block.terminator {
925 self.visit_terminator(location.block, terminator, location)
928 let statement = & $($mutability)*
929 basic_block.statements[location.statement_index];
930 self.visit_statement(location.block, statement, location)
937 make_mir_visitor!(Visitor,);
938 make_mir_visitor!(MutVisitor,mut);
940 pub trait MirVisitable<'tcx> {
941 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
944 impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
945 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
947 visitor.visit_statement(location.block, self, location)
951 impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
952 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
954 visitor.visit_terminator(location.block, self, location)
958 impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
959 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
961 visitor.visit_terminator(location.block, self.as_ref().unwrap(), location)
965 /// Extra information passed to `visit_ty` and friends to give context
966 /// about where the type etc appears.
967 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
970 /// The index of the local variable we are visiting.
973 /// The source location where this local variable was declared.
974 source_info: SourceInfo,
977 /// The return type of the function.
978 ReturnTy(SourceInfo),
982 /// A type found at some location.
986 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
987 pub enum NonMutatingUseContext<'tcx> {
988 /// Being inspected in some way, like loading a len.
990 /// Consumed as part of an operand.
992 /// Consumed as part of an operand.
995 SharedBorrow(Region<'tcx>),
997 ShallowBorrow(Region<'tcx>),
999 UniqueBorrow(Region<'tcx>),
1000 /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1001 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1009 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1010 pub enum MutatingUseContext<'tcx> {
1011 /// Appears as LHS of an assignment.
1013 /// Can often be treated as a `Store`, but needs to be separate because
1014 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1015 /// cannot be simplified the way a `Store`-`Store` can be.
1017 /// Destination of a call.
1022 Borrow(Region<'tcx>),
1023 /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1024 /// For example, the projection `x.y` is marked as a mutation in these cases:
1030 /// Retagging, a "Stacked Borrows" shadow state operation
1034 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1035 pub enum NonUseContext {
1036 /// Starting a storage live range.
1038 /// Ending a storage live range.
1040 /// User type annotation assertions for NLL.
1044 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1045 pub enum PlaceContext<'tcx> {
1046 NonMutatingUse(NonMutatingUseContext<'tcx>),
1047 MutatingUse(MutatingUseContext<'tcx>),
1048 NonUse(NonUseContext),
1051 impl<'tcx> PlaceContext<'tcx> {
1052 /// Returns `true` if this place context represents a drop.
1053 pub fn is_drop(&self) -> bool {
1055 PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
1060 /// Returns `true` if this place context represents a borrow.
1061 pub fn is_borrow(&self) -> bool {
1063 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
1064 PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
1065 PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
1066 PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) => true,
1071 /// Returns `true` if this place context represents a storage live or storage dead marker.
1072 pub fn is_storage_marker(&self) -> bool {
1074 PlaceContext::NonUse(NonUseContext::StorageLive) |
1075 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1080 /// Returns `true` if this place context represents a storage live marker.
1081 pub fn is_storage_live_marker(&self) -> bool {
1083 PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1088 /// Returns `true` if this place context represents a storage dead marker.
1089 pub fn is_storage_dead_marker(&self) -> bool {
1091 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1096 /// Returns `true` if this place context represents a use that potentially changes the value.
1097 pub fn is_mutating_use(&self) -> bool {
1099 PlaceContext::MutatingUse(..) => true,
1104 /// Returns `true` if this place context represents a use that does not change the value.
1105 pub fn is_nonmutating_use(&self) -> bool {
1107 PlaceContext::NonMutatingUse(..) => true,
1112 /// Returns `true` if this place context represents a use.
1113 pub fn is_use(&self) -> bool {
1115 PlaceContext::NonUse(..) => false,
1120 /// Returns `true` if this place context represents an assignment statement.
1121 pub fn is_place_assignment(&self) -> bool {
1123 PlaceContext::MutatingUse(MutatingUseContext::Store) |
1124 PlaceContext::MutatingUse(MutatingUseContext::Call) |
1125 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true,