@@ -47,6 +47,21 @@ pub trait Delegate<'tcx> {
47
47
/// the id of the binding in the pattern `pat`.
48
48
fn consume ( & mut self , place_with_id : & PlaceWithHirId < ' tcx > , diag_expr_id : HirId ) ;
49
49
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
+
50
65
/// The value found at `place` is being borrowed with kind `bk`.
51
66
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
52
67
fn borrow (
@@ -91,6 +106,10 @@ impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D {
91
106
( * * self ) . consume ( place_with_id, diag_expr_id)
92
107
}
93
108
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
+
94
113
fn borrow (
95
114
& mut self ,
96
115
place_with_id : & PlaceWithHirId < ' tcx > ,
@@ -143,6 +162,8 @@ pub trait TypeInformationCtxt<'tcx> {
143
162
144
163
fn type_is_copy_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
145
164
165
+ fn type_is_use_cloned_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
166
+
146
167
fn body_owner_def_id ( & self ) -> LocalDefId ;
147
168
148
169
fn tcx ( & self ) -> TyCtxt < ' tcx > ;
@@ -184,6 +205,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
184
205
self . infcx . type_is_copy_modulo_regions ( self . param_env , ty)
185
206
}
186
207
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
+
187
212
fn body_owner_def_id ( & self ) -> LocalDefId {
188
213
self . body_id
189
214
}
@@ -230,6 +255,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
230
255
self . 0 . type_is_copy_modulo_regions ( ty)
231
256
}
232
257
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
+
233
262
fn body_owner_def_id ( & self ) -> LocalDefId {
234
263
self . 1
235
264
}
@@ -313,6 +342,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
313
342
Ok ( ( ) )
314
343
}
315
344
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
+
316
362
fn mutate_expr ( & self , expr : & hir:: Expr < ' _ > ) -> Result < ( ) , Cx :: Error > {
317
363
let place_with_id = self . cat_expr ( expr) ?;
318
364
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
367
413
}
368
414
369
415
hir:: ExprKind :: Use ( expr, _) => {
370
- self . consume_expr ( expr) ?;
416
+ self . consume_or_clone_expr ( expr) ?;
371
417
}
372
418
373
419
hir:: ExprKind :: MethodCall ( .., receiver, args, _) => {
0 commit comments