2
2
//! normal visitor, which just walks the entire body in one shot, the
3
3
//! `ExprUseVisitor` determines how expressions are being used.
4
4
5
- pub use self :: ConsumeMode :: * ;
6
-
7
5
// Export these here so that Clippy can use them.
8
6
pub use rustc_middle:: hir:: place:: { Place , PlaceBase , PlaceWithHirId , Projection } ;
9
7
@@ -28,19 +26,20 @@ use crate::mem_categorization as mc;
28
26
/// This trait defines the callbacks you can expect to receive when
29
27
/// employing the ExprUseVisitor.
30
28
pub trait Delegate < ' tcx > {
31
- // The value found at `place` is either copied or moved, depending
29
+ // The value found at `place` is moved, depending
32
30
// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
33
31
//
32
+ // Use of a `Copy` type in a ByValue context is considered a use
33
+ // by `ImmBorrow` and `borrow` is called instead. This is because
34
+ // a shared borrow is the "minimum access" that would be needed
35
+ // to perform a copy.
36
+ //
37
+ //
34
38
// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
35
39
// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
36
40
// id will be the id of the expression `expr` but the place itself will have
37
41
// the id of the binding in the pattern `pat`.
38
- fn consume (
39
- & mut self ,
40
- place_with_id : & PlaceWithHirId < ' tcx > ,
41
- diag_expr_id : hir:: HirId ,
42
- mode : ConsumeMode ,
43
- ) ;
42
+ fn consume ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : hir:: HirId ) ;
44
43
45
44
// The value found at `place` is being borrowed with kind `bk`.
46
45
// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
@@ -60,7 +59,7 @@ pub trait Delegate<'tcx> {
60
59
}
61
60
62
61
#[ derive( Copy , Clone , PartialEq , Debug ) ]
63
- pub enum ConsumeMode {
62
+ enum ConsumeMode {
64
63
Copy , // reference to x where x has a type that copies
65
64
Move , // reference to x where x has a type that moves
66
65
}
@@ -141,10 +140,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
141
140
}
142
141
143
142
fn delegate_consume ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : hir:: HirId ) {
144
- debug ! ( "delegate_consume(place_with_id={:?})" , place_with_id) ;
145
-
146
- let mode = copy_or_move ( & self . mc , place_with_id) ;
147
- self . delegate . consume ( place_with_id, diag_expr_id, mode) ;
143
+ delegate_consume ( & self . mc , self . delegate , place_with_id, diag_expr_id)
148
144
}
149
145
150
146
fn consume_exprs ( & mut self , exprs : & [ hir:: Expr < ' _ > ] ) {
@@ -256,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
256
252
| PatKind :: Path ( ..)
257
253
| PatKind :: Struct ( ..)
258
254
| PatKind :: Tuple ( ..) => {
259
- // If the PatKind is a TupleStruct, Struct or Tuple then we want to check
255
+ // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check
260
256
// whether the Variant is a MultiVariant or a SingleVariant. We only want
261
257
// to borrow discr if it is a MultiVariant.
262
258
// If it is a SingleVariant and creates a binding we will handle that when
263
259
// this callback gets called again.
264
- if let ty:: Adt ( def, _) = place. place. base_ty. kind( ) {
260
+
261
+ // Get the type of the Place after all projections have been applied
262
+ let place_ty = place. place. ty( ) ;
263
+
264
+ if let ty:: Adt ( def, _) = place_ty. kind( ) {
265
265
if def. variants. len( ) > 1 {
266
266
needs_to_be_read = true ;
267
267
}
@@ -653,9 +653,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
653
653
delegate. borrow( place, discr_place. hir_id, bk) ;
654
654
}
655
655
ty:: BindByValue ( ..) => {
656
- let mode = copy_or_move( mc, & place) ;
657
656
debug!( "walk_pat binding consuming pat" ) ;
658
- delegate . consume ( place, discr_place. hir_id, mode ) ;
657
+ delegate_consume ( mc , * delegate , place, discr_place. hir_id) ;
659
658
}
660
659
}
661
660
}
@@ -773,8 +772,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
773
772
774
773
match capture_info. capture_kind {
775
774
ty:: UpvarCapture :: ByValue ( _) => {
776
- let mode = copy_or_move ( & self . mc , & place_with_id) ;
777
- self . delegate . consume ( & place_with_id, place_with_id. hir_id , mode) ;
775
+ self . delegate_consume ( & place_with_id, place_with_id. hir_id ) ;
778
776
}
779
777
ty:: UpvarCapture :: ByRef ( upvar_borrow) => {
780
778
self . delegate . borrow (
@@ -798,8 +796,28 @@ fn copy_or_move<'a, 'tcx>(
798
796
place_with_id. place . ty ( ) ,
799
797
mc. tcx ( ) . hir ( ) . span ( place_with_id. hir_id ) ,
800
798
) {
801
- Move
799
+ ConsumeMode :: Move
802
800
} else {
803
- Copy
801
+ ConsumeMode :: Copy
802
+ }
803
+ }
804
+
805
+ // - If a place is used in a `ByValue` context then move it if it's not a `Copy` type.
806
+ // - If the place that is a `Copy` type consider it a `ImmBorrow`.
807
+ fn delegate_consume < ' a , ' tcx > (
808
+ mc : & mc:: MemCategorizationContext < ' a , ' tcx > ,
809
+ delegate : & mut ( dyn Delegate < ' tcx > + ' a ) ,
810
+ place_with_id : & PlaceWithHirId < ' tcx > ,
811
+ diag_expr_id : hir:: HirId ,
812
+ ) {
813
+ debug ! ( "delegate_consume(place_with_id={:?})" , place_with_id) ;
814
+
815
+ let mode = copy_or_move ( & mc, place_with_id) ;
816
+
817
+ match mode {
818
+ ConsumeMode :: Move => delegate. consume ( place_with_id, diag_expr_id) ,
819
+ ConsumeMode :: Copy => {
820
+ delegate. borrow ( place_with_id, diag_expr_id, ty:: BorrowKind :: ImmBorrow )
821
+ }
804
822
}
805
823
}
0 commit comments