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}
;
16 use rustc_const_math
::ConstUsize
;
17 use rustc_data_structures
::indexed_vec
::Idx
;
24 // There are two visitors, one for immutable and one for mutable references,
25 // but both are generated by the following macro. The code is written according
26 // to the following conventions:
28 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
29 // - `visit_foo`, by default, calls `super_foo`
30 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
32 // This allows you as a user to override `visit_foo` for types are
33 // interested in, and invoke (within that method) call
34 // `self.super_foo` to get the default behavior. Just as in an OO
35 // language, you should never call `super` methods ordinarily except
36 // in that circumstance.
38 // For the most part, we do not destructure things external to the
39 // MIR, e.g. types, spans, etc, but simply visit them and stop. This
40 // avoids duplication with other visitors like `TypeFoldable`.
44 // The code is written in a very deliberate style intended to minimize
45 // the chance of things being overlooked. You'll notice that we always
46 // use pattern matching to reference fields and we ensure that all
47 // matches are exhaustive.
49 // For example, the `super_basic_block_data` method begins like this:
52 // fn super_basic_block_data(&mut self,
54 // data: & $($mutability)* BasicBlockData<'tcx>) {
55 // let BasicBlockData {
56 // ref $($mutability)* statements,
57 // ref $($mutability)* terminator,
61 // for statement in statements {
62 // self.visit_statement(block, statement);
69 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
70 // rather than writing `data.statements` in the body. This is because if one
71 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
72 // and hence one will (hopefully) invoke the correct visit methods (if any).
74 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
75 // That means you never write `..` to skip over fields, nor do you write `_`
76 // to skip over variants in a `match`.
78 // The only place that `_` is acceptable is to match a field (or
79 // variant argument) that does not require visiting, as in
80 // `is_cleanup` above.
82 macro_rules
! make_mir_visitor
{
83 ($visitor_trait_name
:ident
, $
($mutability
:ident
)*) => {
84 pub trait $visitor_trait_name
<'tcx
> {
85 // Override these, and call `self.super_xxx` to revert back to the
88 fn visit_mir(&mut self, mir
: & $
($mutability
)* Mir
<'tcx
>) {
92 fn visit_basic_block_data(&mut self,
94 data
: & $
($mutability
)* BasicBlockData
<'tcx
>) {
95 self.super_basic_block_data(block
, data
);
98 fn visit_visibility_scope_data(&mut self,
99 scope_data
: & $
($mutability
)* VisibilityScopeData
) {
100 self.super_visibility_scope_data(scope_data
);
103 fn visit_statement(&mut self,
105 statement
: & $
($mutability
)* Statement
<'tcx
>,
106 location
: Location
) {
107 self.super_statement(block
, statement
, location
);
110 fn visit_assign(&mut self,
112 lvalue
: & $
($mutability
)* Lvalue
<'tcx
>,
113 rvalue
: & $
($mutability
)* Rvalue
<'tcx
>,
114 location
: Location
) {
115 self.super_assign(block
, lvalue
, rvalue
, location
);
118 fn visit_terminator(&mut self,
120 terminator
: & $
($mutability
)* Terminator
<'tcx
>,
121 location
: Location
) {
122 self.super_terminator(block
, terminator
, location
);
125 fn visit_terminator_kind(&mut self,
127 kind
: & $
($mutability
)* TerminatorKind
<'tcx
>,
128 location
: Location
) {
129 self.super_terminator_kind(block
, kind
, location
);
132 fn visit_assert_message(&mut self,
133 msg
: & $
($mutability
)* AssertMessage
<'tcx
>,
134 location
: Location
) {
135 self.super_assert_message(msg
, location
);
138 fn visit_rvalue(&mut self,
139 rvalue
: & $
($mutability
)* Rvalue
<'tcx
>,
140 location
: Location
) {
141 self.super_rvalue(rvalue
, location
);
144 fn visit_operand(&mut self,
145 operand
: & $
($mutability
)* Operand
<'tcx
>,
146 location
: Location
) {
147 self.super_operand(operand
, location
);
150 fn visit_lvalue(&mut self,
151 lvalue
: & $
($mutability
)* Lvalue
<'tcx
>,
152 context
: LvalueContext
<'tcx
>,
153 location
: Location
) {
154 self.super_lvalue(lvalue
, context
, location
);
157 fn visit_static(&mut self,
158 static_
: & $
($mutability
)* Static
<'tcx
>,
159 context
: LvalueContext
<'tcx
>,
160 location
: Location
) {
161 self.super_static(static_
, context
, location
);
164 fn visit_projection(&mut self,
165 lvalue
: & $
($mutability
)* LvalueProjection
<'tcx
>,
166 context
: LvalueContext
<'tcx
>,
167 location
: Location
) {
168 self.super_projection(lvalue
, context
, location
);
171 fn visit_projection_elem(&mut self,
172 lvalue
: & $
($mutability
)* LvalueElem
<'tcx
>,
173 context
: LvalueContext
<'tcx
>,
174 location
: Location
) {
175 self.super_projection_elem(lvalue
, context
, location
);
178 fn visit_branch(&mut self,
180 target
: BasicBlock
) {
181 self.super_branch(source
, target
);
184 fn visit_constant(&mut self,
185 constant
: & $
($mutability
)* Constant
<'tcx
>,
186 location
: Location
) {
187 self.super_constant(constant
, location
);
190 fn visit_literal(&mut self,
191 literal
: & $
($mutability
)* Literal
<'tcx
>,
192 location
: Location
) {
193 self.super_literal(literal
, location
);
196 fn visit_def_id(&mut self,
197 def_id
: & $
($mutability
)* DefId
,
199 self.super_def_id(def_id
);
202 fn visit_span(&mut self,
203 span
: & $
($mutability
)* Span
) {
204 self.super_span(span
);
207 fn visit_source_info(&mut self,
208 source_info
: & $
($mutability
)* SourceInfo
) {
209 self.super_source_info(source_info
);
212 fn visit_ty(&mut self,
213 ty
: & $
($mutability
)* Ty
<'tcx
>) {
217 fn visit_substs(&mut self,
218 substs
: & $
($mutability
)* &'tcx Substs
<'tcx
>) {
219 self.super_substs(substs
);
222 fn visit_closure_substs(&mut self,
223 substs
: & $
($mutability
)* ClosureSubsts
<'tcx
>) {
224 self.super_closure_substs(substs
);
227 fn visit_const_val(&mut self,
228 const_val
: & $
($mutability
)* ConstVal
,
230 self.super_const_val(const_val
);
233 fn visit_const_int(&mut self,
234 const_int
: &ConstInt
,
236 self.super_const_int(const_int
);
239 fn visit_const_usize(&mut self,
240 const_usize
: & $
($mutability
)* ConstUsize
,
242 self.super_const_usize(const_usize
);
245 fn visit_local_decl(&mut self,
246 local_decl
: & $
($mutability
)* LocalDecl
<'tcx
>) {
247 self.super_local_decl(local_decl
);
250 fn visit_visibility_scope(&mut self,
251 scope
: & $
($mutability
)* VisibilityScope
) {
252 self.super_visibility_scope(scope
);
255 // The `super_xxx` methods comprise the default behavior and are
256 // not meant to be overridden.
258 fn super_mir(&mut self,
259 mir
: & $
($mutability
)* Mir
<'tcx
>) {
260 for index
in 0..mir
.basic_blocks().len() {
261 let block
= BasicBlock
::new(index
);
262 self.visit_basic_block_data(block
, &$
($mutability
)* mir
[block
]);
265 for scope
in &$
($mutability
)* mir
.visibility_scopes
{
266 self.visit_visibility_scope_data(scope
);
269 self.visit_ty(&$
($mutability
)* mir
.return_ty
);
271 for local_decl
in &$
($mutability
)* mir
.local_decls
{
272 self.visit_local_decl(local_decl
);
275 self.visit_span(&$
($mutability
)* mir
.span
);
278 fn super_basic_block_data(&mut self,
280 data
: & $
($mutability
)* BasicBlockData
<'tcx
>) {
282 ref $
($mutability
)* statements
,
283 ref $
($mutability
)* terminator
,
288 for statement
in statements
{
289 let location
= Location { block: block, statement_index: index }
;
290 self.visit_statement(block
, statement
, location
);
294 if let Some(ref $
($mutability
)* terminator
) = *terminator
{
295 let location
= Location { block: block, statement_index: index }
;
296 self.visit_terminator(block
, terminator
, location
);
300 fn super_visibility_scope_data(&mut self,
301 scope_data
: & $
($mutability
)* VisibilityScopeData
) {
302 let VisibilityScopeData
{
303 ref $
($mutability
)* span
,
304 ref $
($mutability
)* parent_scope
,
307 self.visit_span(span
);
308 if let Some(ref $
($mutability
)* parent_scope
) = *parent_scope
{
309 self.visit_visibility_scope(parent_scope
);
313 fn super_statement(&mut self,
315 statement
: & $
($mutability
)* Statement
<'tcx
>,
316 location
: Location
) {
318 ref $
($mutability
)* source_info
,
319 ref $
($mutability
)* kind
,
322 self.visit_source_info(source_info
);
324 StatementKind
::Assign(ref $
($mutability
)* lvalue
,
325 ref $
($mutability
)* rvalue
) => {
326 self.visit_assign(block
, lvalue
, rvalue
, location
);
328 StatementKind
::SetDiscriminant{ ref $($mutability)* lvalue, .. }
=> {
329 self.visit_lvalue(lvalue
, LvalueContext
::Store
, location
);
331 StatementKind
::StorageLive(ref $
($mutability
)* lvalue
) => {
332 self.visit_lvalue(lvalue
, LvalueContext
::StorageLive
, location
);
334 StatementKind
::StorageDead(ref $
($mutability
)* lvalue
) => {
335 self.visit_lvalue(lvalue
, LvalueContext
::StorageDead
, location
);
337 StatementKind
::InlineAsm
{ ref $
($mutability
)* outputs
,
338 ref $
($mutability
)* inputs
,
340 for output
in & $
($mutability
)* outputs
[..] {
341 self.visit_lvalue(output
, LvalueContext
::Store
, location
);
343 for input
in & $
($mutability
)* inputs
[..] {
344 self.visit_operand(input
, location
);
347 StatementKind
::Nop
=> {}
351 fn super_assign(&mut self,
353 lvalue
: &$
($mutability
)* Lvalue
<'tcx
>,
354 rvalue
: &$
($mutability
)* Rvalue
<'tcx
>,
355 location
: Location
) {
356 self.visit_lvalue(lvalue
, LvalueContext
::Store
, location
);
357 self.visit_rvalue(rvalue
, location
);
360 fn super_terminator(&mut self,
362 terminator
: &$
($mutability
)* Terminator
<'tcx
>,
363 location
: Location
) {
365 ref $
($mutability
)* source_info
,
366 ref $
($mutability
)* kind
,
369 self.visit_source_info(source_info
);
370 self.visit_terminator_kind(block
, kind
, location
);
373 fn super_terminator_kind(&mut self,
375 kind
: & $
($mutability
)* TerminatorKind
<'tcx
>,
376 source_location
: Location
) {
378 TerminatorKind
::Goto { target }
=> {
379 self.visit_branch(block
, target
);
382 TerminatorKind
::SwitchInt
{ ref $
($mutability
)* discr
,
383 ref $
($mutability
)* switch_ty
,
386 self.visit_operand(discr
, source_location
);
387 self.visit_ty(switch_ty
);
388 for value
in &values
[..] {
389 self.visit_const_int(value
, source_location
);
391 for &target
in targets
{
392 self.visit_branch(block
, target
);
396 TerminatorKind
::Resume
|
397 TerminatorKind
::Return
|
398 TerminatorKind
::Unreachable
=> {
401 TerminatorKind
::Drop
{ ref $
($mutability
)* location
,
404 self.visit_lvalue(location
, LvalueContext
::Drop
, source_location
);
405 self.visit_branch(block
, target
);
406 unwind
.map(|t
| self.visit_branch(block
, t
));
409 TerminatorKind
::DropAndReplace
{ ref $
($mutability
)* location
,
410 ref $
($mutability
)* value
,
413 self.visit_lvalue(location
, LvalueContext
::Drop
, source_location
);
414 self.visit_operand(value
, source_location
);
415 self.visit_branch(block
, target
);
416 unwind
.map(|t
| self.visit_branch(block
, t
));
419 TerminatorKind
::Call
{ ref $
($mutability
)* func
,
420 ref $
($mutability
)* args
,
421 ref $
($mutability
)* destination
,
423 self.visit_operand(func
, source_location
);
425 self.visit_operand(arg
, source_location
);
427 if let Some((ref $
($mutability
)* destination
, target
)) = *destination
{
428 self.visit_lvalue(destination
, LvalueContext
::Call
, source_location
);
429 self.visit_branch(block
, target
);
431 cleanup
.map(|t
| self.visit_branch(block
, t
));
434 TerminatorKind
::Assert
{ ref $
($mutability
)* cond
,
436 ref $
($mutability
)* msg
,
439 self.visit_operand(cond
, source_location
);
440 self.visit_assert_message(msg
, source_location
);
441 self.visit_branch(block
, target
);
442 cleanup
.map(|t
| self.visit_branch(block
, t
));
447 fn super_assert_message(&mut self,
448 msg
: & $
($mutability
)* AssertMessage
<'tcx
>,
449 location
: Location
) {
451 AssertMessage
::BoundsCheck
{
452 ref $
($mutability
)* len
,
453 ref $
($mutability
)* index
455 self.visit_operand(len
, location
);
456 self.visit_operand(index
, location
);
458 AssertMessage
::Math(_
) => {}
462 fn super_rvalue(&mut self,
463 rvalue
: & $
($mutability
)* Rvalue
<'tcx
>,
464 location
: Location
) {
466 Rvalue
::Use(ref $
($mutability
)* operand
) => {
467 self.visit_operand(operand
, location
);
470 Rvalue
::Repeat(ref $
($mutability
)* value
,
471 ref $
($mutability
)* length
) => {
472 self.visit_operand(value
, location
);
473 self.visit_const_usize(length
, location
);
476 Rvalue
::Ref(r
, bk
, ref $
($mutability
)* path
) => {
477 self.visit_lvalue(path
, LvalueContext
::Borrow
{
483 Rvalue
::Len(ref $
($mutability
)* path
) => {
484 self.visit_lvalue(path
, LvalueContext
::Inspect
, location
);
487 Rvalue
::Cast(_cast_kind
,
488 ref $
($mutability
)* operand
,
489 ref $
($mutability
)* ty
) => {
490 self.visit_operand(operand
, location
);
494 Rvalue
::BinaryOp(_bin_op
,
495 ref $
($mutability
)* lhs
,
496 ref $
($mutability
)* rhs
) |
497 Rvalue
::CheckedBinaryOp(_bin_op
,
498 ref $
($mutability
)* lhs
,
499 ref $
($mutability
)* rhs
) => {
500 self.visit_operand(lhs
, location
);
501 self.visit_operand(rhs
, location
);
504 Rvalue
::UnaryOp(_un_op
, ref $
($mutability
)* op
) => {
505 self.visit_operand(op
, location
);
508 Rvalue
::Discriminant(ref $
($mutability
)* lvalue
) => {
509 self.visit_lvalue(lvalue
, LvalueContext
::Inspect
, location
);
512 Rvalue
::NullaryOp(_op
, ref $
($mutability
)* ty
) => {
516 Rvalue
::Aggregate(ref $
($mutability
)* kind
,
517 ref $
($mutability
)* operands
) => {
518 let kind
= &$
($mutability
)* **kind
;
520 AggregateKind
::Array(ref $
($mutability
)* ty
) => {
523 AggregateKind
::Tuple
=> {
525 AggregateKind
::Adt(_adt_def
,
527 ref $
($mutability
)* substs
,
528 _active_field_index
) => {
529 self.visit_substs(substs
);
531 AggregateKind
::Closure(ref $
($mutability
)* def_id
,
532 ref $
($mutability
)* closure_substs
) => {
533 self.visit_def_id(def_id
, location
);
534 self.visit_closure_substs(closure_substs
);
538 for operand
in operands
{
539 self.visit_operand(operand
, location
);
545 fn super_operand(&mut self,
546 operand
: & $
($mutability
)* Operand
<'tcx
>,
547 location
: Location
) {
549 Operand
::Consume(ref $
($mutability
)* lvalue
) => {
550 self.visit_lvalue(lvalue
, LvalueContext
::Consume
, location
);
552 Operand
::Constant(ref $
($mutability
)* constant
) => {
553 self.visit_constant(constant
, location
);
558 fn super_lvalue(&mut self,
559 lvalue
: & $
($mutability
)* Lvalue
<'tcx
>,
560 context
: LvalueContext
<'tcx
>,
561 location
: Location
) {
563 Lvalue
::Local(_
) => {
565 Lvalue
::Static(ref $
($mutability
)* static_
) => {
566 self.visit_static(static_
, context
, location
);
568 Lvalue
::Projection(ref $
($mutability
)* proj
) => {
569 self.visit_projection(proj
, context
, location
);
574 fn super_static(&mut self,
575 static_
: & $
($mutability
)* Static
<'tcx
>,
576 _context
: LvalueContext
<'tcx
>,
577 location
: Location
) {
579 ref $
($mutability
)* def_id
,
580 ref $
($mutability
)* ty
,
582 self.visit_def_id(def_id
, location
);
586 fn super_projection(&mut self,
587 proj
: & $
($mutability
)* LvalueProjection
<'tcx
>,
588 context
: LvalueContext
<'tcx
>,
589 location
: Location
) {
591 ref $
($mutability
)* base
,
592 ref $
($mutability
)* elem
,
594 let context
= if context
.is_mutating_use() {
595 LvalueContext
::Projection(Mutability
::Mut
)
597 LvalueContext
::Projection(Mutability
::Not
)
599 self.visit_lvalue(base
, context
, location
);
600 self.visit_projection_elem(elem
, context
, location
);
603 fn super_projection_elem(&mut self,
604 proj
: & $
($mutability
)* LvalueElem
<'tcx
>,
605 _context
: LvalueContext
<'tcx
>,
606 location
: Location
) {
608 ProjectionElem
::Deref
=> {
610 ProjectionElem
::Subslice { from: _, to: _ }
=> {
612 ProjectionElem
::Field(_field
, ref $
($mutability
)* ty
) => {
615 ProjectionElem
::Index(ref $
($mutability
)* operand
) => {
616 self.visit_operand(operand
, location
);
618 ProjectionElem
::ConstantIndex
{ offset
: _
,
622 ProjectionElem
::Downcast(_adt_def
, _variant_index
) => {
627 fn super_local_decl(&mut self,
628 local_decl
: & $
($mutability
)* LocalDecl
<'tcx
>) {
631 ref $
($mutability
)* ty
,
633 ref $
($mutability
)* source_info
,
638 self.visit_source_info(source_info
);
641 fn super_visibility_scope(&mut self,
642 _scope
: & $
($mutability
)* VisibilityScope
) {
645 fn super_branch(&mut self,
647 _target
: BasicBlock
) {
650 fn super_constant(&mut self,
651 constant
: & $
($mutability
)* Constant
<'tcx
>,
652 location
: Location
) {
654 ref $
($mutability
)* span
,
655 ref $
($mutability
)* ty
,
656 ref $
($mutability
)* literal
,
659 self.visit_span(span
);
661 self.visit_literal(literal
, location
);
664 fn super_literal(&mut self,
665 literal
: & $
($mutability
)* Literal
<'tcx
>,
666 location
: Location
) {
668 Literal
::Item
{ ref $
($mutability
)* def_id
,
669 ref $
($mutability
)* substs
} => {
670 self.visit_def_id(def_id
, location
);
671 self.visit_substs(substs
);
673 Literal
::Value { ref $($mutability)* value }
=> {
674 self.visit_const_val(value
, location
);
676 Literal
::Promoted { index: _ }
=> {}
680 fn super_def_id(&mut self, _def_id
: & $
($mutability
)* DefId
) {
683 fn super_span(&mut self, _span
: & $
($mutability
)* Span
) {
686 fn super_source_info(&mut self, source_info
: & $
($mutability
)* SourceInfo
) {
688 ref $
($mutability
)* span
,
689 ref $
($mutability
)* scope
,
692 self.visit_span(span
);
693 self.visit_visibility_scope(scope
);
696 fn super_ty(&mut self, _ty
: & $
($mutability
)* Ty
<'tcx
>) {
699 fn super_substs(&mut self, _substs
: & $
($mutability
)* &'tcx Substs
<'tcx
>) {
702 fn super_closure_substs(&mut self,
703 _substs
: & $
($mutability
)* ClosureSubsts
<'tcx
>) {
706 fn super_const_val(&mut self, _const_val
: & $
($mutability
)* ConstVal
) {
709 fn super_const_int(&mut self, _const_int
: &ConstInt
) {
712 fn super_const_usize(&mut self, _const_usize
: & $
($mutability
)* ConstUsize
) {
715 // Convenience methods
717 fn visit_location(&mut self, mir
: & $
($mutability
)* Mir
<'tcx
>, location
: Location
) {
718 let basic_block
= & $
($mutability
)* mir
[location
.block
];
719 if basic_block
.statements
.len() == location
.statement_index
{
720 if let Some(ref $
($mutability
)* terminator
) = basic_block
.terminator
{
721 self.visit_terminator(location
.block
, terminator
, location
)
724 let statement
= & $
($mutability
)*
725 basic_block
.statements
[location
.statement_index
];
726 self.visit_statement(location
.block
, statement
, location
)
733 make_mir_visitor
!(Visitor
,);
734 make_mir_visitor
!(MutVisitor
,mut);
736 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
737 pub enum LvalueContext
<'tcx
> {
738 // Appears as LHS of an assignment
747 // Being inspected in some way, like loading a len
751 Borrow { region: Region<'tcx>, kind: BorrowKind }
,
753 // Used as base for another lvalue, e.g. `x` in `x.y`.
755 // The `Mutability` argument specifies whether the projection is being performed in order to
756 // (potentially) mutate the lvalue. For example, the projection `x.y` is marked as a mutation
762 // But not in these cases:
766 Projection(Mutability
),
768 // Consumed as part of an operand
771 // Starting and ending a storage live range
776 impl<'tcx
> LvalueContext
<'tcx
> {
777 /// Returns true if this lvalue context represents a drop.
778 pub fn is_drop(&self) -> bool
{
780 LvalueContext
::Drop
=> true,
785 /// Returns true if this lvalue context represents a storage live or storage dead marker.
786 pub fn is_storage_marker(&self) -> bool
{
788 LvalueContext
::StorageLive
| LvalueContext
::StorageDead
=> true,
793 /// Returns true if this lvalue context represents a storage live marker.
794 pub fn is_storage_live_marker(&self) -> bool
{
796 LvalueContext
::StorageLive
=> true,
801 /// Returns true if this lvalue context represents a storage dead marker.
802 pub fn is_storage_dead_marker(&self) -> bool
{
804 LvalueContext
::StorageDead
=> true,
809 /// Returns true if this lvalue context represents a use that potentially changes the value.
810 pub fn is_mutating_use(&self) -> bool
{
812 LvalueContext
::Store
| LvalueContext
::Call
|
813 LvalueContext
::Borrow { kind: BorrowKind::Mut, .. }
|
814 LvalueContext
::Projection(Mutability
::Mut
) |
815 LvalueContext
::Drop
=> true,
816 LvalueContext
::Inspect
|
817 LvalueContext
::Borrow { kind: BorrowKind::Shared, .. }
|
818 LvalueContext
::Borrow { kind: BorrowKind::Unique, .. }
|
819 LvalueContext
::Projection(Mutability
::Not
) | LvalueContext
::Consume
|
820 LvalueContext
::StorageLive
| LvalueContext
::StorageDead
=> false,
824 /// Returns true if this lvalue context represents a use that does not change the value.
825 pub fn is_nonmutating_use(&self) -> bool
{
827 LvalueContext
::Inspect
| LvalueContext
::Borrow { kind: BorrowKind::Shared, .. }
|
828 LvalueContext
::Borrow { kind: BorrowKind::Unique, .. }
|
829 LvalueContext
::Projection(Mutability
::Not
) | LvalueContext
::Consume
=> true,
830 LvalueContext
::Borrow { kind: BorrowKind::Mut, .. }
| LvalueContext
::Store
|
831 LvalueContext
::Call
| LvalueContext
::Projection(Mutability
::Mut
) |
832 LvalueContext
::Drop
| LvalueContext
::StorageLive
| LvalueContext
::StorageDead
=> false,
836 pub fn is_use(&self) -> bool
{
837 self.is_mutating_use() || self.is_nonmutating_use()