@@ -175,12 +175,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
175
175
let mut is_loop_move = false ;
176
176
let mut in_pattern = false ;
177
177
178
+ let mut to_clone_spans = Vec :: new ( ) ;
179
+
178
180
for move_site in & move_site_vec {
179
181
let move_out = self . move_data . moves [ ( * move_site) . moi ] ;
180
182
let moved_place = & self . move_data . move_paths [ move_out. path ] . place ;
181
183
182
184
let move_spans = self . move_spans ( moved_place. as_ref ( ) , move_out. source ) ;
183
185
let move_span = move_spans. args_or_use ( ) ;
186
+ to_clone_spans. push ( move_spans. var_or_use_path_span ( ) ) ;
184
187
185
188
let move_msg = if move_spans. for_closure ( ) { " into closure" } else { "" } ;
186
189
@@ -293,18 +296,62 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
293
296
. and_then ( |def_id| tcx. hir ( ) . get_generics ( def_id) )
294
297
{
295
298
let copy_did = tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ;
296
- let predicates =
299
+ let copy_predicates =
297
300
self . try_find_missing_generic_bounds ( ty, copy_did, generics, span) ;
298
301
299
- if let Ok ( predicates) = predicates {
300
- suggest_constraining_type_params (
301
- tcx,
302
- hir_generics,
303
- & mut err,
304
- predicates. iter ( ) . map ( |( param, constraint) | {
305
- ( param. name . as_str ( ) , & * * constraint, None )
306
- } ) ,
307
- ) ;
302
+ let clone_did = tcx. lang_items ( ) . clone_trait ( ) . unwrap ( ) ;
303
+ let clone_predicates =
304
+ self . try_find_missing_generic_bounds ( ty, clone_did, generics, span) ;
305
+
306
+ match ( copy_predicates, clone_predicates) {
307
+ // The type is already `Clone`, suggest cloning all values
308
+ ( _, Ok ( clone_predicates) ) if clone_predicates. is_empty ( ) => {
309
+ err. multipart_suggestion_verbose (
310
+ & format ! ( "consider cloning {}" , note_msg) ,
311
+ to_clone_spans
312
+ . into_iter ( )
313
+ . map ( |move_span| {
314
+ ( move_span. shrink_to_hi ( ) , ".clone()" . to_owned ( ) )
315
+ } )
316
+ . collect ( ) ,
317
+ Applicability :: MaybeIncorrect ,
318
+ ) ;
319
+ }
320
+ // The type can *not* be `Copy`, but can be `Clone`, suggest adding bounds to make the type `Clone` and then cloning all values
321
+ ( Err ( _) , Ok ( clone_predicates) ) => {
322
+ suggest_constraining_type_params (
323
+ tcx,
324
+ hir_generics,
325
+ & mut err,
326
+ clone_predicates. iter ( ) . map ( |( param, constraint) | {
327
+ ( param. name . as_str ( ) , & * * constraint, None )
328
+ } ) ,
329
+ ) ;
330
+
331
+ err. multipart_suggestion_verbose (
332
+ & format ! ( "...and cloning {}" , note_msg) ,
333
+ to_clone_spans
334
+ . into_iter ( )
335
+ . map ( |move_span| {
336
+ ( move_span. shrink_to_hi ( ) , ".clone()" . to_owned ( ) )
337
+ } )
338
+ . collect ( ) ,
339
+ Applicability :: MaybeIncorrect ,
340
+ ) ;
341
+ }
342
+ // The type can be `Copy`, suggest adding bound to make it `Copy`
343
+ ( Ok ( copy_predicates) , _) => {
344
+ suggest_constraining_type_params (
345
+ tcx,
346
+ hir_generics,
347
+ & mut err,
348
+ copy_predicates. iter ( ) . map ( |( param, constraint) | {
349
+ ( param. name . as_str ( ) , & * * constraint, None )
350
+ } ) ,
351
+ ) ;
352
+ }
353
+ // The type can never be `Clone` or `Copy`, there is nothing to suggest :(
354
+ ( Err ( _) , Err ( _) ) => { }
308
355
}
309
356
}
310
357
0 commit comments