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::SetDiscriminant{ ref $($mutability)* place, .. } => {
383 PlaceContext::MutatingUse(MutatingUseContext::Store),
387 StatementKind::EscapeToRaw(ref $($mutability)* op) => {
388 self.visit_operand(op, location);
390 StatementKind::StorageLive(ref $($mutability)* local) => {
393 PlaceContext::NonUse(NonUseContext::StorageLive),
397 StatementKind::StorageDead(ref $($mutability)* local) => {
400 PlaceContext::NonUse(NonUseContext::StorageDead),
404 StatementKind::InlineAsm { ref $($mutability)* outputs,
405 ref $($mutability)* inputs,
407 for output in & $($mutability)* outputs[..] {
410 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
414 for (span, input) in & $($mutability)* inputs[..] {
415 self.visit_span(span);
416 self.visit_operand(input, location);
419 StatementKind::Retag { ref $($mutability)* fn_entry,
420 ref $($mutability)* place } => {
421 self.visit_retag(fn_entry, place, location);
423 StatementKind::AscribeUserType(
424 ref $($mutability)* place,
425 ref $($mutability)* variance,
426 ref $($mutability)* user_ty,
428 self.visit_ascribe_user_ty(place, variance, user_ty, location);
430 StatementKind::Nop => {}
434 fn super_assign(&mut self,
436 place: &$($mutability)* Place<'tcx>,
437 rvalue: &$($mutability)* Rvalue<'tcx>,
438 location: Location) {
441 PlaceContext::MutatingUse(MutatingUseContext::Store),
444 self.visit_rvalue(rvalue, location);
447 fn super_terminator(&mut self,
449 terminator: &$($mutability)* Terminator<'tcx>,
450 location: Location) {
452 ref $($mutability)* source_info,
453 ref $($mutability)* kind,
456 self.visit_source_info(source_info);
457 self.visit_terminator_kind(block, kind, location);
460 fn super_terminator_kind(&mut self,
462 kind: & $($mutability)* TerminatorKind<'tcx>,
463 source_location: Location) {
465 TerminatorKind::Goto { target } => {
466 self.visit_branch(block, target);
469 TerminatorKind::SwitchInt { ref $($mutability)* discr,
470 ref $($mutability)* switch_ty,
473 self.visit_operand(discr, source_location);
474 self.visit_ty(switch_ty, TyContext::Location(source_location));
475 for &target in targets {
476 self.visit_branch(block, target);
480 TerminatorKind::Resume |
481 TerminatorKind::Abort |
482 TerminatorKind::Return |
483 TerminatorKind::GeneratorDrop |
484 TerminatorKind::Unreachable => {
487 TerminatorKind::Drop { ref $($mutability)* location,
492 PlaceContext::MutatingUse(MutatingUseContext::Drop),
495 self.visit_branch(block, target);
496 unwind.map(|t| self.visit_branch(block, t));
499 TerminatorKind::DropAndReplace { ref $($mutability)* location,
500 ref $($mutability)* value,
505 PlaceContext::MutatingUse(MutatingUseContext::Drop),
508 self.visit_operand(value, source_location);
509 self.visit_branch(block, target);
510 unwind.map(|t| self.visit_branch(block, t));
513 TerminatorKind::Call { ref $($mutability)* func,
514 ref $($mutability)* args,
515 ref $($mutability)* destination,
517 from_hir_call: _, } => {
518 self.visit_operand(func, source_location);
520 self.visit_operand(arg, source_location);
522 if let Some((ref $($mutability)* destination, target)) = *destination {
525 PlaceContext::MutatingUse(MutatingUseContext::Call),
528 self.visit_branch(block, target);
530 cleanup.map(|t| self.visit_branch(block, t));
533 TerminatorKind::Assert { ref $($mutability)* cond,
535 ref $($mutability)* msg,
538 self.visit_operand(cond, source_location);
539 self.visit_assert_message(msg, source_location);
540 self.visit_branch(block, target);
541 cleanup.map(|t| self.visit_branch(block, t));
544 TerminatorKind::Yield { ref $($mutability)* value,
547 self.visit_operand(value, source_location);
548 self.visit_branch(block, resume);
549 drop.map(|t| self.visit_branch(block, t));
552 TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => {
553 self.visit_branch(block, real_target);
554 for target in imaginary_targets {
555 self.visit_branch(block, *target);
559 TerminatorKind::FalseUnwind { real_target, unwind } => {
560 self.visit_branch(block, real_target);
561 if let Some(unwind) = unwind {
562 self.visit_branch(block, unwind);
568 fn super_assert_message(&mut self,
569 msg: & $($mutability)* AssertMessage<'tcx>,
570 location: Location) {
571 use mir::interpret::EvalErrorKind::*;
573 ref $($mutability)* len,
574 ref $($mutability)* index
576 self.visit_operand(len, location);
577 self.visit_operand(index, location);
581 fn super_rvalue(&mut self,
582 rvalue: & $($mutability)* Rvalue<'tcx>,
583 location: Location) {
585 Rvalue::Use(ref $($mutability)* operand) => {
586 self.visit_operand(operand, location);
589 Rvalue::Repeat(ref $($mutability)* value, _) => {
590 self.visit_operand(value, location);
593 Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
594 self.visit_region(r, location);
596 BorrowKind::Shared => PlaceContext::NonMutatingUse(
597 NonMutatingUseContext::SharedBorrow(*r)
599 BorrowKind::Shallow => PlaceContext::NonMutatingUse(
600 NonMutatingUseContext::ShallowBorrow(*r)
602 BorrowKind::Unique => PlaceContext::NonMutatingUse(
603 NonMutatingUseContext::UniqueBorrow(*r)
605 BorrowKind::Mut { .. } =>
606 PlaceContext::MutatingUse(MutatingUseContext::Borrow(*r)),
608 self.visit_place(path, ctx, location);
611 Rvalue::Len(ref $($mutability)* path) => {
614 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
619 Rvalue::Cast(_cast_kind,
620 ref $($mutability)* operand,
621 ref $($mutability)* ty) => {
622 self.visit_operand(operand, location);
623 self.visit_ty(ty, TyContext::Location(location));
626 Rvalue::BinaryOp(_bin_op,
627 ref $($mutability)* lhs,
628 ref $($mutability)* rhs) |
629 Rvalue::CheckedBinaryOp(_bin_op,
630 ref $($mutability)* lhs,
631 ref $($mutability)* rhs) => {
632 self.visit_operand(lhs, location);
633 self.visit_operand(rhs, location);
636 Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
637 self.visit_operand(op, location);
640 Rvalue::Discriminant(ref $($mutability)* place) => {
643 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
648 Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
649 self.visit_ty(ty, TyContext::Location(location));
652 Rvalue::Aggregate(ref $($mutability)* kind,
653 ref $($mutability)* operands) => {
654 let kind = &$($mutability)* **kind;
656 AggregateKind::Array(ref $($mutability)* ty) => {
657 self.visit_ty(ty, TyContext::Location(location));
659 AggregateKind::Tuple => {
661 AggregateKind::Adt(_adt_def,
663 ref $($mutability)* substs,
665 _active_field_index) => {
666 self.visit_substs(substs, location);
668 AggregateKind::Closure(ref $($mutability)* def_id,
669 ref $($mutability)* closure_substs) => {
670 self.visit_def_id(def_id, location);
671 self.visit_closure_substs(closure_substs, location);
673 AggregateKind::Generator(ref $($mutability)* def_id,
674 ref $($mutability)* generator_substs,
676 self.visit_def_id(def_id, location);
677 self.visit_generator_substs(generator_substs, location);
681 for operand in operands {
682 self.visit_operand(operand, location);
688 fn super_operand(&mut self,
689 operand: & $($mutability)* Operand<'tcx>,
690 location: Location) {
692 Operand::Copy(ref $($mutability)* place) => {
695 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
699 Operand::Move(ref $($mutability)* place) => {
702 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
706 Operand::Constant(ref $($mutability)* constant) => {
707 self.visit_constant(constant, location);
712 fn super_ascribe_user_ty(&mut self,
713 place: & $($mutability)* Place<'tcx>,
714 _variance: & $($mutability)* ty::Variance,
715 user_ty: & $($mutability)* UserTypeProjection<'tcx>,
716 location: Location) {
719 PlaceContext::NonUse(NonUseContext::AscribeUserTy),
722 self.visit_user_type_projection(user_ty);
725 fn super_retag(&mut self,
726 _fn_entry: & $($mutability)* bool,
727 place: & $($mutability)* Place<'tcx>,
728 location: Location) {
731 PlaceContext::MutatingUse(MutatingUseContext::Retag),
736 fn super_place(&mut self,
737 place: & $($mutability)* Place<'tcx>,
738 context: PlaceContext<'tcx>,
739 location: Location) {
741 Place::Local(ref $($mutability)* local) => {
742 self.visit_local(local, context, location);
744 Place::Static(ref $($mutability)* static_) => {
745 self.visit_static(static_, context, location);
747 Place::Promoted(ref $($mutability)* promoted) => {
748 self.visit_ty(& $($mutability)* promoted.1, TyContext::Location(location));
750 Place::Projection(ref $($mutability)* proj) => {
751 self.visit_projection(proj, context, location);
756 fn super_static(&mut self,
757 static_: & $($mutability)* Static<'tcx>,
758 _context: PlaceContext<'tcx>,
759 location: Location) {
761 ref $($mutability)* def_id,
762 ref $($mutability)* ty,
764 self.visit_def_id(def_id, location);
765 self.visit_ty(ty, TyContext::Location(location));
768 fn super_projection(&mut self,
769 proj: & $($mutability)* PlaceProjection<'tcx>,
770 context: PlaceContext<'tcx>,
771 location: Location) {
773 ref $($mutability)* base,
774 ref $($mutability)* elem,
776 let context = if context.is_mutating_use() {
777 PlaceContext::MutatingUse(MutatingUseContext::Projection)
779 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
781 self.visit_place(base, context, location);
782 self.visit_projection_elem(elem, location);
785 fn super_projection_elem(&mut self,
786 proj: & $($mutability)* PlaceElem<'tcx>,
787 location: Location) {
789 ProjectionElem::Deref => {
791 ProjectionElem::Subslice { from: _, to: _ } => {
793 ProjectionElem::Field(_field, ref $($mutability)* ty) => {
794 self.visit_ty(ty, TyContext::Location(location));
796 ProjectionElem::Index(ref $($mutability)* local) => {
799 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
803 ProjectionElem::ConstantIndex { offset: _,
807 ProjectionElem::Downcast(_adt_def, _variant_index) => {
812 fn super_local_decl(&mut self,
814 local_decl: & $($mutability)* LocalDecl<'tcx>) {
817 ref $($mutability)* ty,
818 ref $($mutability)* user_ty,
820 ref $($mutability)* source_info,
821 ref $($mutability)* visibility_scope,
827 self.visit_ty(ty, TyContext::LocalDecl {
829 source_info: *source_info,
831 for (user_ty, _) in & $($mutability)* user_ty.contents {
832 self.visit_user_type_projection(user_ty);
834 self.visit_source_info(source_info);
835 self.visit_source_scope(visibility_scope);
838 fn super_source_scope(&mut self,
839 _scope: & $($mutability)* SourceScope) {
842 fn super_branch(&mut self,
844 _target: BasicBlock) {
847 fn super_constant(&mut self,
848 constant: & $($mutability)* Constant<'tcx>,
849 location: Location) {
851 ref $($mutability)* span,
852 ref $($mutability)* ty,
853 ref $($mutability)* user_ty,
854 ref $($mutability)* literal,
857 self.visit_span(span);
858 self.visit_ty(ty, TyContext::Location(location));
859 drop(user_ty); // no visit method for this
860 self.visit_const(literal, location);
863 fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
866 fn super_span(&mut self, _span: & $($mutability)* Span) {
869 fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
871 ref $($mutability)* span,
872 ref $($mutability)* scope,
875 self.visit_span(span);
876 self.visit_source_scope(scope);
879 fn super_user_type_projection(
881 ty: & $($mutability)* UserTypeProjection<'tcx>,
883 let UserTypeProjection {
884 ref $($mutability)* base,
885 projs: _, // Note: Does not visit projection elems!
887 self.visit_user_type_annotation(base);
890 fn super_user_type_annotation(
892 _ty: & $($mutability)* UserTypeAnnotation<'tcx>,
896 fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
899 fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
902 fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) {
905 fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
908 fn super_generator_substs(&mut self,
909 _substs: & $($mutability)* GeneratorSubsts<'tcx>) {
912 fn super_closure_substs(&mut self,
913 _substs: & $($mutability)* ClosureSubsts<'tcx>) {
916 // Convenience methods
918 fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
919 let basic_block = & $($mutability)* mir[location.block];
920 if basic_block.statements.len() == location.statement_index {
921 if let Some(ref $($mutability)* terminator) = basic_block.terminator {
922 self.visit_terminator(location.block, terminator, location)
925 let statement = & $($mutability)*
926 basic_block.statements[location.statement_index];
927 self.visit_statement(location.block, statement, location)
934 make_mir_visitor!(Visitor,);
935 make_mir_visitor!(MutVisitor,mut);
937 pub trait MirVisitable<'tcx> {
938 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
941 impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
942 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
944 visitor.visit_statement(location.block, self, location)
948 impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
949 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
951 visitor.visit_terminator(location.block, self, location)
955 impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
956 fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
958 visitor.visit_terminator(location.block, self.as_ref().unwrap(), location)
962 /// Extra information passed to `visit_ty` and friends to give context
963 /// about where the type etc appears.
964 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
967 /// The index of the local variable we are visiting.
970 /// The source location where this local variable was declared.
971 source_info: SourceInfo,
974 /// The return type of the function.
975 ReturnTy(SourceInfo),
979 /// A type found at some location.
983 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
984 pub enum NonMutatingUseContext<'tcx> {
985 /// Being inspected in some way, like loading a len.
987 /// Consumed as part of an operand.
989 /// Consumed as part of an operand.
992 SharedBorrow(Region<'tcx>),
994 ShallowBorrow(Region<'tcx>),
996 UniqueBorrow(Region<'tcx>),
997 /// Used as base for another place, e.g. `x` in `x.y`. Will not mutate the place.
998 /// For example, the projection `x.y` is not marked as a mutation in these cases:
1006 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1007 pub enum MutatingUseContext<'tcx> {
1008 /// Appears as LHS of an assignment.
1010 /// Can often be treated as a `Store`, but needs to be separate because
1011 /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
1012 /// cannot be simplified the way a `Store`-`Store` can be.
1014 /// Destination of a call.
1019 Borrow(Region<'tcx>),
1020 /// Used as base for another place, e.g. `x` in `x.y`. Could potentially mutate the place.
1021 /// For example, the projection `x.y` is marked as a mutation in these cases:
1027 /// Retagging, a "Stacked Borrows" shadow state operation
1031 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1032 pub enum NonUseContext {
1033 /// Starting a storage live range.
1035 /// Ending a storage live range.
1037 /// User type annotation assertions for NLL.
1041 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1042 pub enum PlaceContext<'tcx> {
1043 NonMutatingUse(NonMutatingUseContext<'tcx>),
1044 MutatingUse(MutatingUseContext<'tcx>),
1045 NonUse(NonUseContext),
1048 impl<'tcx> PlaceContext<'tcx> {
1049 /// Returns `true` if this place context represents a drop.
1050 pub fn is_drop(&self) -> bool {
1052 PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
1057 /// Returns `true` if this place context represents a borrow.
1058 pub fn is_borrow(&self) -> bool {
1060 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
1061 PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
1062 PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
1063 PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) => true,
1068 /// Returns `true` if this place context represents a storage live or storage dead marker.
1069 pub fn is_storage_marker(&self) -> bool {
1071 PlaceContext::NonUse(NonUseContext::StorageLive) |
1072 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1077 /// Returns `true` if this place context represents a storage live marker.
1078 pub fn is_storage_live_marker(&self) -> bool {
1080 PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1085 /// Returns `true` if this place context represents a storage dead marker.
1086 pub fn is_storage_dead_marker(&self) -> bool {
1088 PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1093 /// Returns `true` if this place context represents a use that potentially changes the value.
1094 pub fn is_mutating_use(&self) -> bool {
1096 PlaceContext::MutatingUse(..) => true,
1101 /// Returns `true` if this place context represents a use that does not change the value.
1102 pub fn is_nonmutating_use(&self) -> bool {
1104 PlaceContext::NonMutatingUse(..) => true,
1109 /// Returns `true` if this place context represents a use.
1110 pub fn is_use(&self) -> bool {
1112 PlaceContext::NonUse(..) => false,
1117 /// Returns `true` if this place context represents an assignment statement.
1118 pub fn is_place_assignment(&self) -> bool {
1120 PlaceContext::MutatingUse(MutatingUseContext::Store) |
1121 PlaceContext::MutatingUse(MutatingUseContext::Call) |
1122 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true,