@@ -47,6 +47,21 @@ pub trait Delegate<'tcx> {
4747 /// the id of the binding in the pattern `pat`.
4848 fn consume ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : HirId ) ;
4949
50+ /// The value found at `place` is moved, depending
51+ /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
52+ ///
53+ /// Use of a `Copy` type in a ByValue context is considered a use
54+ /// by `ImmBorrow` and `borrow` is called instead. This is because
55+ /// a shared borrow is the "minimum access" that would be needed
56+ /// to perform a copy.
57+ ///
58+ ///
59+ /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
60+ /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
61+ /// id will be the id of the expression `expr` but the place itself will have
62+ /// the id of the binding in the pattern `pat`.
63+ fn use_cloned ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : HirId ) ;
64+
5065 /// The value found at `place` is being borrowed with kind `bk`.
5166 /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
5267 fn borrow (
@@ -91,6 +106,10 @@ impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D {
91106 ( * * self ) . consume ( place_with_id, diag_expr_id)
92107 }
93108
109+ fn use_cloned ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : HirId ) {
110+ ( * * self ) . use_cloned ( place_with_id, diag_expr_id)
111+ }
112+
94113 fn borrow (
95114 & mut self ,
96115 place_with_id : & PlaceWithHirId < ' tcx > ,
@@ -143,6 +162,8 @@ pub trait TypeInformationCtxt<'tcx> {
143162
144163 fn type_is_copy_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
145164
165+ fn type_is_use_cloned_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
166+
146167 fn body_owner_def_id ( & self ) -> LocalDefId ;
147168
148169 fn tcx ( & self ) -> TyCtxt < ' tcx > ;
@@ -184,6 +205,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
184205 self . infcx . type_is_copy_modulo_regions ( self . param_env , ty)
185206 }
186207
208+ fn type_is_use_cloned_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool {
209+ self . infcx . type_is_use_cloned_modulo_regions ( self . param_env , ty)
210+ }
211+
187212 fn body_owner_def_id ( & self ) -> LocalDefId {
188213 self . body_id
189214 }
@@ -230,6 +255,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
230255 self . 0 . type_is_copy_modulo_regions ( ty)
231256 }
232257
258+ fn type_is_use_cloned_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool {
259+ self . 0 . type_is_use_cloned_modulo_regions ( ty)
260+ }
261+
233262 fn body_owner_def_id ( & self ) -> LocalDefId {
234263 self . 1
235264 }
@@ -313,6 +342,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
313342 Ok ( ( ) )
314343 }
315344
345+ pub fn consume_or_clone_expr ( & self , expr : & hir:: Expr < ' _ > ) -> Result < ( ) , Cx :: Error > {
346+ debug ! ( "consume_or_clone_expr(expr={:?})" , expr) ;
347+
348+ let place_with_id = self . cat_expr ( expr) ?;
349+
350+ if self . cx . type_is_copy_modulo_regions ( place_with_id. place . ty ( ) ) {
351+ self . delegate . borrow_mut ( ) . copy ( & place_with_id, place_with_id. hir_id ) ;
352+ } else if self . cx . type_is_use_cloned_modulo_regions ( place_with_id. place . ty ( ) ) {
353+ self . delegate . borrow_mut ( ) . use_cloned ( & place_with_id, place_with_id. hir_id ) ;
354+ } else {
355+ self . delegate . borrow_mut ( ) . consume ( & place_with_id, place_with_id. hir_id ) ;
356+ }
357+
358+ self . walk_expr ( expr) ?;
359+ Ok ( ( ) )
360+ }
361+
316362 fn mutate_expr ( & self , expr : & hir:: Expr < ' _ > ) -> Result < ( ) , Cx :: Error > {
317363 let place_with_id = self . cat_expr ( expr) ?;
318364 self . delegate . borrow_mut ( ) . mutate ( & place_with_id, place_with_id. hir_id ) ;
@@ -367,7 +413,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
367413 }
368414
369415 hir:: ExprKind :: Use ( expr, _) => {
370- self . consume_expr ( expr) ?;
416+ self . consume_or_clone_expr ( expr) ?;
371417 }
372418
373419 hir:: ExprKind :: MethodCall ( .., receiver, args, _) => {
0 commit comments