22//! normal visitor, which just walks the entire body in one shot, the 
33//! `ExprUseVisitor` determines how expressions are being used. 
44
5- pub  use  self :: ConsumeMode :: * ; 
6- 
75// Export these here so that Clippy can use them. 
86pub  use  rustc_middle:: hir:: place:: { Place ,  PlaceBase ,  PlaceWithHirId ,  Projection } ; 
97
@@ -28,19 +26,20 @@ use crate::mem_categorization as mc;
2826/// This trait defines the callbacks you can expect to receive when 
2927/// employing the ExprUseVisitor. 
3028pub  trait  Delegate < ' tcx >  { 
31-     // The value found at `place` is either copied or  moved, depending 
29+     // The value found at `place` is moved, depending 
3230    // on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`. 
3331    // 
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+     // 
3438    // The parameter `diag_expr_id` indicates the HIR id that ought to be used for 
3539    // diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic 
3640    // id will be the id of the expression `expr` but the place itself will have 
3741    // 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 ) ; 
4443
4544    // The value found at `place` is being borrowed with kind `bk`. 
4645    // `diag_expr_id` is the id used for diagnostics (see `consume` for more details). 
@@ -60,7 +59,7 @@ pub trait Delegate<'tcx> {
6059} 
6160
6261#[ derive( Copy ,  Clone ,  PartialEq ,  Debug ) ]  
63- pub   enum  ConsumeMode  { 
62+ enum  ConsumeMode  { 
6463    Copy ,  // reference to x where x has a type that copies 
6564    Move ,  // reference to x where x has a type that moves 
6665} 
@@ -141,10 +140,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
141140    } 
142141
143142    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) 
148144    } 
149145
150146    fn  consume_exprs ( & mut  self ,  exprs :  & [ hir:: Expr < ' _ > ] )  { 
@@ -256,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
256252                            | PatKind :: Path ( ..) 
257253                            | PatKind :: Struct ( ..) 
258254                            | 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 
260256                                // whether the Variant is a MultiVariant or a SingleVariant. We only want 
261257                                // to borrow discr if it is a MultiVariant. 
262258                                // If it is a SingleVariant and creates a binding we will handle that when 
263259                                // 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( )  { 
265265                                    if  def. variants. len( )  > 1  { 
266266                                        needs_to_be_read = true ; 
267267                                    } 
@@ -653,9 +653,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
653653                            delegate. borrow( place,  discr_place. hir_id,  bk) ; 
654654                        } 
655655                        ty:: BindByValue ( ..)  => { 
656-                             let  mode = copy_or_move( mc,  & place) ; 
657656                            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) ; 
659658                        } 
660659                    } 
661660                } 
@@ -773,8 +772,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
773772
774773                    match  capture_info. capture_kind  { 
775774                        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 ) ; 
778776                        } 
779777                        ty:: UpvarCapture :: ByRef ( upvar_borrow)  => { 
780778                            self . delegate . borrow ( 
@@ -798,8 +796,28 @@ fn copy_or_move<'a, 'tcx>(
798796        place_with_id. place . ty ( ) , 
799797        mc. tcx ( ) . hir ( ) . span ( place_with_id. hir_id ) , 
800798    )  { 
801-         Move 
799+         ConsumeMode :: Move 
802800    }  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+         } 
804822    } 
805823} 
0 commit comments