@@ -192,146 +192,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
192
192
is_loop_move = true ;
193
193
}
194
194
195
- struct ExpressionFinder < ' hir > {
196
- expr_span : Span ,
197
- expr : Option < & ' hir hir:: Expr < ' hir > > ,
198
- pat : Option < & ' hir hir:: Pat < ' hir > > ,
199
- }
200
- impl < ' hir > Visitor < ' hir > for ExpressionFinder < ' hir > {
201
- fn visit_expr ( & mut self , e : & ' hir hir:: Expr < ' hir > ) {
202
- if e. span == self . expr_span {
203
- self . expr = Some ( e) ;
204
- }
205
- hir:: intravisit:: walk_expr ( self , e) ;
206
- }
207
- fn visit_pat ( & mut self , p : & ' hir hir:: Pat < ' hir > ) {
208
- if p. span == self . expr_span {
209
- self . pat = Some ( p) ;
210
- }
211
- if let hir:: PatKind :: Binding ( hir:: BindingAnnotation :: NONE , _, i, _) = p. kind
212
- && i. span == self . expr_span
213
- {
214
- self . pat = Some ( p) ;
215
- }
216
- hir:: intravisit:: walk_pat ( self , p) ;
217
- }
218
- }
219
-
220
- let hir = self . infcx . tcx . hir ( ) ;
221
- if let Some ( hir:: Node :: Item ( hir:: Item {
222
- kind : hir:: ItemKind :: Fn ( _, _, body_id) ,
223
- ..
224
- } ) ) = hir. find ( hir. local_def_id_to_hir_id ( self . mir_def_id ( ) ) )
225
- && let Some ( hir:: Node :: Expr ( expr) ) = hir. find ( body_id. hir_id )
226
- {
227
- let place = & self . move_data . move_paths [ mpi] . place ;
228
- let span = place. as_local ( )
229
- . map ( |local| self . body . local_decls [ local] . source_info . span ) ;
230
- let mut finder = ExpressionFinder {
231
- expr_span : move_span,
232
- expr : None ,
233
- pat : None ,
234
- } ;
235
- finder. visit_expr ( expr) ;
236
- if let Some ( span) = span && let Some ( expr) = finder. expr {
237
- for ( _, expr) in hir. parent_iter ( expr. hir_id ) {
238
- if let hir:: Node :: Expr ( expr) = expr {
239
- if expr. span . contains ( span) {
240
- // If the let binding occurs within the same loop, then that
241
- // loop isn't relevant, like in the following, the outermost `loop`
242
- // doesn't play into `x` being moved.
243
- // ```
244
- // loop {
245
- // let x = String::new();
246
- // loop {
247
- // foo(x);
248
- // }
249
- // }
250
- // ```
251
- break ;
252
- }
253
- if let hir:: ExprKind :: Loop ( .., loop_span) = expr. kind {
254
- err. span_label ( loop_span, "inside of this loop" ) ;
255
- }
256
- }
257
- }
258
- let typeck = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
259
- let hir_id = hir. get_parent_node ( expr. hir_id ) ;
260
- if let Some ( parent) = hir. find ( hir_id) {
261
- if let hir:: Node :: Expr ( parent_expr) = parent
262
- && let hir:: ExprKind :: MethodCall ( _, _, args, _) = parent_expr. kind
263
- && let Some ( def_id) = typeck. type_dependent_def_id ( parent_expr. hir_id )
264
- && let Some ( def_id) = def_id. as_local ( )
265
- && let Some ( node) = hir. find ( hir. local_def_id_to_hir_id ( def_id) )
266
- && let Some ( fn_sig) = node. fn_sig ( )
267
- && let Some ( ident) = node. ident ( )
268
- && let Some ( pos) = args. iter ( )
269
- . position ( |arg| arg. hir_id == expr. hir_id )
270
- && let Some ( arg) = fn_sig. decl . inputs . get ( pos + 1 )
271
- {
272
- let mut span: MultiSpan = arg. span . into ( ) ;
273
- span. push_span_label (
274
- arg. span ,
275
- "this type parameter takes ownership of the value" . to_string ( ) ,
276
- ) ;
277
- span. push_span_label (
278
- ident. span ,
279
- "in this method" . to_string ( ) ,
280
- ) ;
281
- err. span_note (
282
- span,
283
- format ! (
284
- "consider changing this parameter type in `{}` to borrow \
285
- instead if ownering the value isn't necessary",
286
- ident,
287
- ) ,
288
- ) ;
289
- }
290
- if let hir:: Node :: Expr ( parent_expr) = parent
291
- && let hir:: ExprKind :: Call ( call, args) = parent_expr. kind
292
- && let ty:: FnDef ( def_id, _) = typeck. node_type ( call. hir_id ) . kind ( )
293
- && let Some ( def_id) = def_id. as_local ( )
294
- && let Some ( node) = hir. find ( hir. local_def_id_to_hir_id ( def_id) )
295
- && let Some ( fn_sig) = node. fn_sig ( )
296
- && let Some ( ident) = node. ident ( )
297
- && let Some ( pos) = args. iter ( )
298
- . position ( |arg| arg. hir_id == expr. hir_id )
299
- && let Some ( arg) = fn_sig. decl . inputs . get ( pos)
300
- {
301
- let mut span: MultiSpan = arg. span . into ( ) ;
302
- span. push_span_label (
303
- arg. span ,
304
- "this type parameter takes ownership of the value" . to_string ( ) ,
305
- ) ;
306
- span. push_span_label (
307
- ident. span ,
308
- "in this function" . to_string ( ) ,
309
- ) ;
310
- err. span_note (
311
- span,
312
- format ! (
313
- "consider changing this parameter type in `{}` to borrow \
314
- instead if ownering the value isn't necessary",
315
- ident,
316
- ) ,
317
- ) ;
318
- }
319
- let place = & self . move_data . move_paths [ mpi] . place ;
320
- let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
321
- self . suggest_cloning ( & mut err, ty, move_span) ;
322
- }
323
- }
324
- if let Some ( pat) = finder. pat && !seen_spans. contains ( & pat. span ) {
325
- in_pattern = true ;
326
- err. span_suggestion_verbose (
327
- pat. span . shrink_to_lo ( ) ,
328
- "borrow this binding in the pattern to avoid moving the value" ,
329
- "ref " . to_string ( ) ,
330
- Applicability :: MachineApplicable ,
331
- ) ;
332
- seen_spans. insert ( pat. span ) ;
333
- }
334
- }
195
+ self . suggest_ref_or_clone (
196
+ mpi,
197
+ move_span,
198
+ & mut err,
199
+ & mut seen_spans,
200
+ & mut in_pattern,
201
+ ) ;
335
202
336
203
self . explain_captures (
337
204
& mut err,
@@ -440,6 +307,155 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
440
307
}
441
308
}
442
309
310
+ fn suggest_ref_or_clone (
311
+ & mut self ,
312
+ mpi : MovePathIndex ,
313
+ move_span : Span ,
314
+ err : & mut DiagnosticBuilder < ' _ , ErrorGuaranteed > ,
315
+ seen_spans : & mut FxHashSet < Span > ,
316
+ in_pattern : & mut bool ,
317
+ ) {
318
+ struct ExpressionFinder < ' hir > {
319
+ expr_span : Span ,
320
+ expr : Option < & ' hir hir:: Expr < ' hir > > ,
321
+ pat : Option < & ' hir hir:: Pat < ' hir > > ,
322
+ }
323
+ impl < ' hir > Visitor < ' hir > for ExpressionFinder < ' hir > {
324
+ fn visit_expr ( & mut self , e : & ' hir hir:: Expr < ' hir > ) {
325
+ if e. span == self . expr_span {
326
+ self . expr = Some ( e) ;
327
+ }
328
+ hir:: intravisit:: walk_expr ( self , e) ;
329
+ }
330
+ fn visit_pat ( & mut self , p : & ' hir hir:: Pat < ' hir > ) {
331
+ if p. span == self . expr_span {
332
+ self . pat = Some ( p) ;
333
+ }
334
+ if let hir:: PatKind :: Binding ( hir:: BindingAnnotation :: NONE , _, i, _) = p. kind
335
+ && i. span == self . expr_span
336
+ {
337
+ self . pat = Some ( p) ;
338
+ }
339
+ hir:: intravisit:: walk_pat ( self , p) ;
340
+ }
341
+ }
342
+ let hir = self . infcx . tcx . hir ( ) ;
343
+ if let Some ( hir:: Node :: Item ( hir:: Item {
344
+ kind : hir:: ItemKind :: Fn ( _, _, body_id) ,
345
+ ..
346
+ } ) ) = hir. find ( hir. local_def_id_to_hir_id ( self . mir_def_id ( ) ) )
347
+ && let Some ( hir:: Node :: Expr ( expr) ) = hir. find ( body_id. hir_id )
348
+ {
349
+ let place = & self . move_data . move_paths [ mpi] . place ;
350
+ let span = place. as_local ( )
351
+ . map ( |local| self . body . local_decls [ local] . source_info . span ) ;
352
+ let mut finder = ExpressionFinder {
353
+ expr_span : move_span,
354
+ expr : None ,
355
+ pat : None ,
356
+ } ;
357
+ finder. visit_expr ( expr) ;
358
+ if let Some ( span) = span && let Some ( expr) = finder. expr {
359
+ for ( _, expr) in hir. parent_iter ( expr. hir_id ) {
360
+ if let hir:: Node :: Expr ( expr) = expr {
361
+ if expr. span . contains ( span) {
362
+ // If the let binding occurs within the same loop, then that
363
+ // loop isn't relevant, like in the following, the outermost `loop`
364
+ // doesn't play into `x` being moved.
365
+ // ```
366
+ // loop {
367
+ // let x = String::new();
368
+ // loop {
369
+ // foo(x);
370
+ // }
371
+ // }
372
+ // ```
373
+ break ;
374
+ }
375
+ if let hir:: ExprKind :: Loop ( .., loop_span) = expr. kind {
376
+ err. span_label ( loop_span, "inside of this loop" ) ;
377
+ }
378
+ }
379
+ }
380
+ let typeck = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
381
+ let hir_id = hir. get_parent_node ( expr. hir_id ) ;
382
+ if let Some ( parent) = hir. find ( hir_id) {
383
+ if let hir:: Node :: Expr ( parent_expr) = parent
384
+ && let hir:: ExprKind :: MethodCall ( _, _, args, _) = parent_expr. kind
385
+ && let Some ( def_id) = typeck. type_dependent_def_id ( parent_expr. hir_id )
386
+ && let Some ( def_id) = def_id. as_local ( )
387
+ && let Some ( node) = hir. find ( hir. local_def_id_to_hir_id ( def_id) )
388
+ && let Some ( fn_sig) = node. fn_sig ( )
389
+ && let Some ( ident) = node. ident ( )
390
+ && let Some ( pos) = args. iter ( )
391
+ . position ( |arg| arg. hir_id == expr. hir_id )
392
+ && let Some ( arg) = fn_sig. decl . inputs . get ( pos + 1 )
393
+ {
394
+ let mut span: MultiSpan = arg. span . into ( ) ;
395
+ span. push_span_label (
396
+ arg. span ,
397
+ "this type parameter takes ownership of the value" . to_string ( ) ,
398
+ ) ;
399
+ span. push_span_label (
400
+ ident. span ,
401
+ "in this method" . to_string ( ) ,
402
+ ) ;
403
+ err. span_note (
404
+ span,
405
+ format ! (
406
+ "consider changing this parameter type in `{}` to borrow instead \
407
+ if ownering the value isn't necessary",
408
+ ident,
409
+ ) ,
410
+ ) ;
411
+ }
412
+ if let hir:: Node :: Expr ( parent_expr) = parent
413
+ && let hir:: ExprKind :: Call ( call, args) = parent_expr. kind
414
+ && let ty:: FnDef ( def_id, _) = typeck. node_type ( call. hir_id ) . kind ( )
415
+ && let Some ( def_id) = def_id. as_local ( )
416
+ && let Some ( node) = hir. find ( hir. local_def_id_to_hir_id ( def_id) )
417
+ && let Some ( fn_sig) = node. fn_sig ( )
418
+ && let Some ( ident) = node. ident ( )
419
+ && let Some ( pos) = args. iter ( )
420
+ . position ( |arg| arg. hir_id == expr. hir_id )
421
+ && let Some ( arg) = fn_sig. decl . inputs . get ( pos)
422
+ {
423
+ let mut span: MultiSpan = arg. span . into ( ) ;
424
+ span. push_span_label (
425
+ arg. span ,
426
+ "this type parameter takes ownership of the value" . to_string ( ) ,
427
+ ) ;
428
+ span. push_span_label (
429
+ ident. span ,
430
+ "in this function" . to_string ( ) ,
431
+ ) ;
432
+ err. span_note (
433
+ span,
434
+ format ! (
435
+ "consider changing this parameter type in `{}` to borrow instead \
436
+ if ownering the value isn't necessary",
437
+ ident,
438
+ ) ,
439
+ ) ;
440
+ }
441
+ let place = & self . move_data . move_paths [ mpi] . place ;
442
+ let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
443
+ self . suggest_cloning ( err, ty, move_span) ;
444
+ }
445
+ }
446
+ if let Some ( pat) = finder. pat && !seen_spans. contains ( & pat. span ) {
447
+ * in_pattern = true ;
448
+ err. span_suggestion_verbose (
449
+ pat. span . shrink_to_lo ( ) ,
450
+ "borrow this binding in the pattern to avoid moving the value" ,
451
+ "ref " . to_string ( ) ,
452
+ Applicability :: MachineApplicable ,
453
+ ) ;
454
+ seen_spans. insert ( pat. span ) ;
455
+ }
456
+ }
457
+ }
458
+
443
459
fn report_use_of_uninitialized (
444
460
& self ,
445
461
mpi : MovePathIndex ,
0 commit comments