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 middle::const_val::ConstVal;
12 use hir::def_id::DefId;
13 use ty::subst::Substs;
14 use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
16 use rustc_const_math::ConstUsize;
23 // There are two visitors, one for immutable and one for mutable references,
24 // but both are generated by the following macro. The code is written according
25 // to the following conventions:
27 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
28 // - `visit_foo`, by default, calls `super_foo`
29 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
31 // This allows you as a user to override `visit_foo` for types are
32 // interested in, and invoke (within that method) call
33 // `self.super_foo` to get the default behavior. Just as in an OO
34 // language, you should never call `super` methods ordinarily except
35 // in that circumstance.
37 // For the most part, we do not destructure things external to the
38 // MIR, e.g. types, spans, etc, but simply visit them and stop. This
39 // avoids duplication with other visitors like `TypeFoldable`.
43 // The code is written in a very deliberate style intended to minimize
44 // the chance of things being overlooked. You'll notice that we always
45 // use pattern matching to reference fields and we ensure that all
46 // matches are exhaustive.
48 // For example, the `super_basic_block_data` method begins like this:
51 // fn super_basic_block_data(&mut self,
53 // data: & $($mutability)* BasicBlockData<'tcx>) {
54 // let BasicBlockData {
55 // ref $($mutability)* statements,
56 // ref $($mutability)* terminator,
60 // for statement in statements {
61 // self.visit_statement(block, statement);
68 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
69 // rather than writing `data.statements` in the body. This is because if one
70 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
71 // and hence one will (hopefully) invoke the correct visit methods (if any).
73 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
74 // That means you never write `..` to skip over fields, nor do you write `_`
75 // to skip over variants in a `match`.
77 // The only place that `_` is acceptable is to match a field (or
78 // variant argument) that does not require visiting, as in
79 // `is_cleanup` above.
81 macro_rules! make_mir_visitor {
82 ($visitor_trait_name:ident, $($mutability:ident)*) => {
83 pub trait $visitor_trait_name<'tcx> {
84 // Override these, and call `self.super_xxx` to revert back to the
87 fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
91 fn visit_basic_block_data(&mut self,
93 data: & $($mutability)* BasicBlockData<'tcx>) {
94 self.super_basic_block_data(block, data);
97 fn visit_visibility_scope_data(&mut self,
98 scope_data: & $($mutability)* VisibilityScopeData) {
99 self.super_visibility_scope_data(scope_data);
102 fn visit_statement(&mut self,
104 statement: & $($mutability)* Statement<'tcx>,
105 location: Location) {
106 self.super_statement(block, statement, location);
109 fn visit_assign(&mut self,
111 lvalue: & $($mutability)* Lvalue<'tcx>,
112 rvalue: & $($mutability)* Rvalue<'tcx>,
113 location: Location) {
114 self.super_assign(block, lvalue, rvalue, location);
117 fn visit_terminator(&mut self,
119 terminator: & $($mutability)* Terminator<'tcx>,
120 location: Location) {
121 self.super_terminator(block, terminator, location);
124 fn visit_terminator_kind(&mut self,
126 kind: & $($mutability)* TerminatorKind<'tcx>,
127 location: Location) {
128 self.super_terminator_kind(block, kind, location);
131 fn visit_assert_message(&mut self,
132 msg: & $($mutability)* AssertMessage<'tcx>,
133 location: Location) {
134 self.super_assert_message(msg, location);
137 fn visit_rvalue(&mut self,
138 rvalue: & $($mutability)* Rvalue<'tcx>,
139 location: Location) {
140 self.super_rvalue(rvalue, location);
143 fn visit_operand(&mut self,
144 operand: & $($mutability)* Operand<'tcx>,
145 location: Location) {
146 self.super_operand(operand, location);
149 fn visit_lvalue(&mut self,
150 lvalue: & $($mutability)* Lvalue<'tcx>,
151 context: LvalueContext<'tcx>,
152 location: Location) {
153 self.super_lvalue(lvalue, context, location);
156 fn visit_static(&mut self,
157 static_: & $($mutability)* Static<'tcx>,
158 context: LvalueContext<'tcx>,
159 location: Location) {
160 self.super_static(static_, context, location);
163 fn visit_projection(&mut self,
164 lvalue: & $($mutability)* LvalueProjection<'tcx>,
165 context: LvalueContext<'tcx>,
166 location: Location) {
167 self.super_projection(lvalue, context, location);
170 fn visit_projection_elem(&mut self,
171 lvalue: & $($mutability)* LvalueElem<'tcx>,
172 context: LvalueContext<'tcx>,
173 location: Location) {
174 self.super_projection_elem(lvalue, context, location);
177 fn visit_branch(&mut self,
179 target: BasicBlock) {
180 self.super_branch(source, target);
183 fn visit_constant(&mut self,
184 constant: & $($mutability)* Constant<'tcx>,
185 location: Location) {
186 self.super_constant(constant, location);
189 fn visit_literal(&mut self,
190 literal: & $($mutability)* Literal<'tcx>,
191 location: Location) {
192 self.super_literal(literal, location);
195 fn visit_def_id(&mut self,
196 def_id: & $($mutability)* DefId,
198 self.super_def_id(def_id);
201 fn visit_span(&mut self,
202 span: & $($mutability)* Span) {
203 self.super_span(span);
206 fn visit_source_info(&mut self,
207 source_info: & $($mutability)* SourceInfo) {
208 self.super_source_info(source_info);
211 fn visit_ty(&mut self,
212 ty: & $($mutability)* Ty<'tcx>,
217 fn visit_substs(&mut self,
218 substs: & $($mutability)* &'tcx Substs<'tcx>,
220 self.super_substs(substs);
223 fn visit_closure_substs(&mut self,
224 substs: & $($mutability)* ClosureSubsts<'tcx>,
226 self.super_closure_substs(substs);
229 fn visit_generator_interior(&mut self,
230 interior: & $($mutability)* GeneratorInterior<'tcx>,
232 self.super_generator_interior(interior);
235 fn visit_const_val(&mut self,
236 const_val: & $($mutability)* ConstVal,
238 self.super_const_val(const_val);
241 fn visit_const_int(&mut self,
242 const_int: &ConstInt,
244 self.super_const_int(const_int);
247 fn visit_const_usize(&mut self,
248 const_usize: & $($mutability)* ConstUsize,
250 self.super_const_usize(const_usize);
253 fn visit_local_decl(&mut self,
254 local_decl: & $($mutability)* LocalDecl<'tcx>) {
255 self.super_local_decl(local_decl);
258 fn visit_local(&mut self,
259 _local: & $($mutability)* Local) {
262 fn visit_visibility_scope(&mut self,
263 scope: & $($mutability)* VisibilityScope) {
264 self.super_visibility_scope(scope);
267 // The `super_xxx` methods comprise the default behavior and are
268 // not meant to be overridden.
270 fn super_mir(&mut self,
271 mir: & $($mutability)* Mir<'tcx>) {
272 // for best performance, we want to use an iterator rather
273 // than a for-loop, to avoid calling Mir::invalidate for
275 macro_rules! basic_blocks {
276 (mut) => (mir.basic_blocks_mut().iter_enumerated_mut());
277 () => (mir.basic_blocks().iter_enumerated());
279 for (bb, data) in basic_blocks!($($mutability)*) {
280 self.visit_basic_block_data(bb, data);
283 for scope in &$($mutability)* mir.visibility_scopes {
284 self.visit_visibility_scope_data(scope);
287 let lookup = Lookup::Src(SourceInfo {
289 scope: ARGUMENT_VISIBILITY_SCOPE,
291 self.visit_ty(&$($mutability)* mir.return_ty, lookup);
293 for local_decl in &$($mutability)* mir.local_decls {
294 self.visit_local_decl(local_decl);
297 self.visit_span(&$($mutability)* mir.span);
300 fn super_basic_block_data(&mut self,
302 data: & $($mutability)* BasicBlockData<'tcx>) {
304 ref $($mutability)* statements,
305 ref $($mutability)* terminator,
310 for statement in statements {
311 let location = Location { block: block, statement_index: index };
312 self.visit_statement(block, statement, location);
316 if let Some(ref $($mutability)* terminator) = *terminator {
317 let location = Location { block: block, statement_index: index };
318 self.visit_terminator(block, terminator, location);
322 fn super_visibility_scope_data(&mut self,
323 scope_data: & $($mutability)* VisibilityScopeData) {
324 let VisibilityScopeData {
325 ref $($mutability)* span,
326 ref $($mutability)* parent_scope,
329 self.visit_span(span);
330 if let Some(ref $($mutability)* parent_scope) = *parent_scope {
331 self.visit_visibility_scope(parent_scope);
335 fn super_statement(&mut self,
337 statement: & $($mutability)* Statement<'tcx>,
338 location: Location) {
340 ref $($mutability)* source_info,
341 ref $($mutability)* kind,
344 self.visit_source_info(source_info);
346 StatementKind::Assign(ref $($mutability)* lvalue,
347 ref $($mutability)* rvalue) => {
348 self.visit_assign(block, lvalue, rvalue, location);
350 StatementKind::EndRegion(_) => {}
351 StatementKind::Validate(_, ref $($mutability)* lvalues) => {
352 for operand in lvalues {
353 self.visit_lvalue(& $($mutability)* operand.lval,
354 LvalueContext::Validate, location);
355 self.visit_ty(& $($mutability)* operand.ty, Lookup::Loc(location));
358 StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
359 self.visit_lvalue(lvalue, LvalueContext::Store, location);
361 StatementKind::StorageLive(ref $($mutability)* lvalue) => {
362 self.visit_lvalue(lvalue, LvalueContext::StorageLive, location);
364 StatementKind::StorageDead(ref $($mutability)* lvalue) => {
365 self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
367 StatementKind::InlineAsm { ref $($mutability)* outputs,
368 ref $($mutability)* inputs,
370 for output in & $($mutability)* outputs[..] {
371 self.visit_lvalue(output, LvalueContext::Store, location);
373 for input in & $($mutability)* inputs[..] {
374 self.visit_operand(input, location);
377 StatementKind::Nop => {}
381 fn super_assign(&mut self,
383 lvalue: &$($mutability)* Lvalue<'tcx>,
384 rvalue: &$($mutability)* Rvalue<'tcx>,
385 location: Location) {
386 self.visit_lvalue(lvalue, LvalueContext::Store, location);
387 self.visit_rvalue(rvalue, location);
390 fn super_terminator(&mut self,
392 terminator: &$($mutability)* Terminator<'tcx>,
393 location: Location) {
395 ref $($mutability)* source_info,
396 ref $($mutability)* kind,
399 self.visit_source_info(source_info);
400 self.visit_terminator_kind(block, kind, location);
403 fn super_terminator_kind(&mut self,
405 kind: & $($mutability)* TerminatorKind<'tcx>,
406 source_location: Location) {
408 TerminatorKind::Goto { target } => {
409 self.visit_branch(block, target);
412 TerminatorKind::SwitchInt { ref $($mutability)* discr,
413 ref $($mutability)* switch_ty,
416 self.visit_operand(discr, source_location);
417 self.visit_ty(switch_ty, Lookup::Loc(source_location));
418 for value in &values[..] {
419 self.visit_const_int(value, source_location);
421 for &target in targets {
422 self.visit_branch(block, target);
426 TerminatorKind::Resume |
427 TerminatorKind::Return |
428 TerminatorKind::GeneratorDrop |
429 TerminatorKind::Unreachable => {
432 TerminatorKind::Drop { ref $($mutability)* location,
435 self.visit_lvalue(location, LvalueContext::Drop, source_location);
436 self.visit_branch(block, target);
437 unwind.map(|t| self.visit_branch(block, t));
440 TerminatorKind::DropAndReplace { ref $($mutability)* location,
441 ref $($mutability)* value,
444 self.visit_lvalue(location, LvalueContext::Drop, source_location);
445 self.visit_operand(value, source_location);
446 self.visit_branch(block, target);
447 unwind.map(|t| self.visit_branch(block, t));
450 TerminatorKind::Call { ref $($mutability)* func,
451 ref $($mutability)* args,
452 ref $($mutability)* destination,
454 self.visit_operand(func, source_location);
456 self.visit_operand(arg, source_location);
458 if let Some((ref $($mutability)* destination, target)) = *destination {
459 self.visit_lvalue(destination, LvalueContext::Call, source_location);
460 self.visit_branch(block, target);
462 cleanup.map(|t| self.visit_branch(block, t));
465 TerminatorKind::Assert { ref $($mutability)* cond,
467 ref $($mutability)* msg,
470 self.visit_operand(cond, source_location);
471 self.visit_assert_message(msg, source_location);
472 self.visit_branch(block, target);
473 cleanup.map(|t| self.visit_branch(block, t));
476 TerminatorKind::Yield { ref $($mutability)* value,
479 self.visit_operand(value, source_location);
480 self.visit_branch(block, resume);
481 drop.map(|t| self.visit_branch(block, t));
487 fn super_assert_message(&mut self,
488 msg: & $($mutability)* AssertMessage<'tcx>,
489 location: Location) {
491 AssertMessage::BoundsCheck {
492 ref $($mutability)* len,
493 ref $($mutability)* index
495 self.visit_operand(len, location);
496 self.visit_operand(index, location);
498 AssertMessage::Math(_) => {},
499 AssertMessage::GeneratorResumedAfterReturn => {},
500 AssertMessage::GeneratorResumedAfterPanic => {},
504 fn super_rvalue(&mut self,
505 rvalue: & $($mutability)* Rvalue<'tcx>,
506 location: Location) {
508 Rvalue::Use(ref $($mutability)* operand) => {
509 self.visit_operand(operand, location);
512 Rvalue::Repeat(ref $($mutability)* value,
513 ref $($mutability)* length) => {
514 self.visit_operand(value, location);
515 self.visit_const_usize(length, location);
518 Rvalue::Ref(r, bk, ref $($mutability)* path) => {
519 self.visit_lvalue(path, LvalueContext::Borrow {
525 Rvalue::Len(ref $($mutability)* path) => {
526 self.visit_lvalue(path, LvalueContext::Inspect, location);
529 Rvalue::Cast(_cast_kind,
530 ref $($mutability)* operand,
531 ref $($mutability)* ty) => {
532 self.visit_operand(operand, location);
533 self.visit_ty(ty, Lookup::Loc(location));
536 Rvalue::BinaryOp(_bin_op,
537 ref $($mutability)* lhs,
538 ref $($mutability)* rhs) |
539 Rvalue::CheckedBinaryOp(_bin_op,
540 ref $($mutability)* lhs,
541 ref $($mutability)* rhs) => {
542 self.visit_operand(lhs, location);
543 self.visit_operand(rhs, location);
546 Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
547 self.visit_operand(op, location);
550 Rvalue::Discriminant(ref $($mutability)* lvalue) => {
551 self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
554 Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
555 self.visit_ty(ty, Lookup::Loc(location));
558 Rvalue::Aggregate(ref $($mutability)* kind,
559 ref $($mutability)* operands) => {
560 let kind = &$($mutability)* **kind;
562 AggregateKind::Array(ref $($mutability)* ty) => {
563 self.visit_ty(ty, Lookup::Loc(location));
565 AggregateKind::Tuple => {
567 AggregateKind::Adt(_adt_def,
569 ref $($mutability)* substs,
570 _active_field_index) => {
571 self.visit_substs(substs, location);
573 AggregateKind::Closure(ref $($mutability)* def_id,
574 ref $($mutability)* closure_substs) => {
575 self.visit_def_id(def_id, location);
576 self.visit_closure_substs(closure_substs, location);
578 AggregateKind::Generator(ref $($mutability)* def_id,
579 ref $($mutability)* closure_substs,
580 ref $($mutability)* interior) => {
581 self.visit_def_id(def_id, location);
582 self.visit_closure_substs(closure_substs, location);
583 self.visit_generator_interior(interior, location);
587 for operand in operands {
588 self.visit_operand(operand, location);
594 fn super_operand(&mut self,
595 operand: & $($mutability)* Operand<'tcx>,
596 location: Location) {
598 Operand::Consume(ref $($mutability)* lvalue) => {
599 self.visit_lvalue(lvalue, LvalueContext::Consume, location);
601 Operand::Constant(ref $($mutability)* constant) => {
602 self.visit_constant(constant, location);
607 fn super_lvalue(&mut self,
608 lvalue: & $($mutability)* Lvalue<'tcx>,
609 context: LvalueContext<'tcx>,
610 location: Location) {
612 Lvalue::Local(ref $($mutability)* local) => {
613 self.visit_local(local);
615 Lvalue::Static(ref $($mutability)* static_) => {
616 self.visit_static(static_, context, location);
618 Lvalue::Projection(ref $($mutability)* proj) => {
619 self.visit_projection(proj, context, location);
624 fn super_static(&mut self,
625 static_: & $($mutability)* Static<'tcx>,
626 _context: LvalueContext<'tcx>,
627 location: Location) {
629 ref $($mutability)* def_id,
630 ref $($mutability)* ty,
632 self.visit_def_id(def_id, location);
633 self.visit_ty(ty, Lookup::Loc(location));
636 fn super_projection(&mut self,
637 proj: & $($mutability)* LvalueProjection<'tcx>,
638 context: LvalueContext<'tcx>,
639 location: Location) {
641 ref $($mutability)* base,
642 ref $($mutability)* elem,
644 let context = if context.is_mutating_use() {
645 LvalueContext::Projection(Mutability::Mut)
647 LvalueContext::Projection(Mutability::Not)
649 self.visit_lvalue(base, context, location);
650 self.visit_projection_elem(elem, context, location);
653 fn super_projection_elem(&mut self,
654 proj: & $($mutability)* LvalueElem<'tcx>,
655 _context: LvalueContext<'tcx>,
656 location: Location) {
658 ProjectionElem::Deref => {
660 ProjectionElem::Subslice { from: _, to: _ } => {
662 ProjectionElem::Field(_field, ref $($mutability)* ty) => {
663 self.visit_ty(ty, Lookup::Loc(location));
665 ProjectionElem::Index(ref $($mutability)* operand) => {
666 self.visit_operand(operand, location);
668 ProjectionElem::ConstantIndex { offset: _,
672 ProjectionElem::Downcast(_adt_def, _variant_index) => {
677 fn super_local_decl(&mut self,
678 local_decl: & $($mutability)* LocalDecl<'tcx>) {
681 ref $($mutability)* ty,
683 ref $($mutability)* source_info,
688 self.visit_ty(ty, Lookup::Src(*source_info));
689 self.visit_source_info(source_info);
692 fn super_visibility_scope(&mut self,
693 _scope: & $($mutability)* VisibilityScope) {
696 fn super_branch(&mut self,
698 _target: BasicBlock) {
701 fn super_constant(&mut self,
702 constant: & $($mutability)* Constant<'tcx>,
703 location: Location) {
705 ref $($mutability)* span,
706 ref $($mutability)* ty,
707 ref $($mutability)* literal,
710 self.visit_span(span);
711 self.visit_ty(ty, Lookup::Loc(location));
712 self.visit_literal(literal, location);
715 fn super_literal(&mut self,
716 literal: & $($mutability)* Literal<'tcx>,
717 location: Location) {
719 Literal::Item { ref $($mutability)* def_id,
720 ref $($mutability)* substs } => {
721 self.visit_def_id(def_id, location);
722 self.visit_substs(substs, location);
724 Literal::Value { ref $($mutability)* value } => {
725 self.visit_const_val(value, location);
727 Literal::Promoted { index: _ } => {}
731 fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
734 fn super_span(&mut self, _span: & $($mutability)* Span) {
737 fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
739 ref $($mutability)* span,
740 ref $($mutability)* scope,
743 self.visit_span(span);
744 self.visit_visibility_scope(scope);
747 fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
750 fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
753 fn super_generator_interior(&mut self,
754 _interior: & $($mutability)* GeneratorInterior<'tcx>) {
757 fn super_closure_substs(&mut self,
758 _substs: & $($mutability)* ClosureSubsts<'tcx>) {
761 fn super_const_val(&mut self, _const_val: & $($mutability)* ConstVal) {
764 fn super_const_int(&mut self, _const_int: &ConstInt) {
767 fn super_const_usize(&mut self, _const_usize: & $($mutability)* ConstUsize) {
770 // Convenience methods
772 fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
773 let basic_block = & $($mutability)* mir[location.block];
774 if basic_block.statements.len() == location.statement_index {
775 if let Some(ref $($mutability)* terminator) = basic_block.terminator {
776 self.visit_terminator(location.block, terminator, location)
779 let statement = & $($mutability)*
780 basic_block.statements[location.statement_index];
781 self.visit_statement(location.block, statement, location)
788 make_mir_visitor!(Visitor,);
789 make_mir_visitor!(MutVisitor,mut);
791 #[derive(Copy, Clone, Debug)]
797 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
798 pub enum LvalueContext<'tcx> {
799 // Appears as LHS of an assignment
808 // Being inspected in some way, like loading a len
812 Borrow { region: Region<'tcx>, kind: BorrowKind },
814 // Used as base for another lvalue, e.g. `x` in `x.y`.
816 // The `Mutability` argument specifies whether the projection is being performed in order to
817 // (potentially) mutate the lvalue. For example, the projection `x.y` is marked as a mutation
823 // But not in these cases:
827 Projection(Mutability),
829 // Consumed as part of an operand
832 // Starting and ending a storage live range
836 // Validation command
840 impl<'tcx> LvalueContext<'tcx> {
841 /// Returns true if this lvalue context represents a drop.
842 pub fn is_drop(&self) -> bool {
844 LvalueContext::Drop => true,
849 /// Returns true if this lvalue context represents a storage live or storage dead marker.
850 pub fn is_storage_marker(&self) -> bool {
852 LvalueContext::StorageLive | LvalueContext::StorageDead => true,
857 /// Returns true if this lvalue context represents a storage live marker.
858 pub fn is_storage_live_marker(&self) -> bool {
860 LvalueContext::StorageLive => true,
865 /// Returns true if this lvalue context represents a storage dead marker.
866 pub fn is_storage_dead_marker(&self) -> bool {
868 LvalueContext::StorageDead => true,
873 /// Returns true if this lvalue context represents a use that potentially changes the value.
874 pub fn is_mutating_use(&self) -> bool {
876 LvalueContext::Store | LvalueContext::Call |
877 LvalueContext::Borrow { kind: BorrowKind::Mut, .. } |
878 LvalueContext::Projection(Mutability::Mut) |
879 LvalueContext::Drop => true,
880 LvalueContext::Inspect |
881 LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
882 LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
883 LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume |
884 LvalueContext::StorageLive | LvalueContext::StorageDead |
885 LvalueContext::Validate => false,
889 /// Returns true if this lvalue context represents a use that does not change the value.
890 pub fn is_nonmutating_use(&self) -> bool {
892 LvalueContext::Inspect | LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
893 LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
894 LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume => true,
895 LvalueContext::Borrow { kind: BorrowKind::Mut, .. } | LvalueContext::Store |
896 LvalueContext::Call | LvalueContext::Projection(Mutability::Mut) |
897 LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead |
898 LvalueContext::Validate => false,
902 pub fn is_use(&self) -> bool {
903 self.is_mutating_use() || self.is_nonmutating_use()