@@ -151,6 +151,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
151151 . args_or_use ( )
152152 } )
153153 . collect :: < Vec < Span > > ( ) ;
154+
154155 let reinits = maybe_reinitialized_locations. len ( ) ;
155156 if reinits == 1 {
156157 err. span_label ( reinit_spans[ 0 ] , "this reinitialization might get skipped" ) ;
@@ -282,69 +283,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
282283 Some ( ref name) => format ! ( "`{}`" , name) ,
283284 None => "value" . to_owned ( ) ,
284285 } ;
285-
286- let tcx = self . infcx . tcx ;
287- let generics = tcx. generics_of ( self . mir_def_id ( ) ) ;
288-
289286 if self . suggest_borrow_fn_like ( & mut err, ty, & move_site_vec, & note_msg) {
290287 // Suppress the next note, since we don't want to put more `Fn`-like bounds onto something that already has them
291288 } else if needs_note {
292- if let Some ( hir_generics) = tcx
293- . typeck_root_def_id ( self . mir_def_id ( ) . to_def_id ( ) )
294- . as_local ( )
295- . and_then ( |def_id| tcx. hir ( ) . get_generics ( def_id) )
296- {
297- // Try to find predicates on *generic params* that would allow copying `ty`
298- let predicates: Result < Vec < _ > , _ > = tcx. infer_ctxt ( ) . enter ( |infcx| {
299- let mut fulfill_cx =
300- <dyn rustc_infer:: traits:: TraitEngine < ' _ > >:: new ( infcx. tcx ) ;
301-
302- let copy_did = infcx. tcx . lang_items ( ) . copy_trait ( ) . unwrap ( ) ;
303- let cause = ObligationCause :: new (
304- span,
305- self . mir_hir_id ( ) ,
306- rustc_infer:: traits:: ObligationCauseCode :: MiscObligation ,
307- ) ;
308- fulfill_cx. register_bound (
309- & infcx,
310- self . param_env ,
311- // Erase any region vids from the type, which may not be resolved
312- infcx. tcx . erase_regions ( ty) ,
313- copy_did,
314- cause,
315- ) ;
316- // Select all, including ambiguous predicates
317- let errors = fulfill_cx. select_all_or_error ( & infcx) ;
318-
319- // Only emit suggestion if all required predicates are on generic
320- errors
321- . into_iter ( )
322- . map ( |err| match err. obligation . predicate . kind ( ) . skip_binder ( ) {
323- PredicateKind :: Trait ( predicate) => {
324- match predicate. self_ty ( ) . kind ( ) {
325- ty:: Param ( param_ty) => Ok ( (
326- generics. type_param ( param_ty, tcx) ,
327- predicate. trait_ref . print_only_trait_path ( ) . to_string ( ) ,
328- ) ) ,
329- _ => Err ( ( ) ) ,
330- }
331- }
332- _ => Err ( ( ) ) ,
333- } )
334- . collect ( )
335- } ) ;
336-
337- if let Ok ( predicates) = predicates {
338- suggest_constraining_type_params (
339- tcx,
340- hir_generics,
341- & mut err,
342- predicates. iter ( ) . map ( |( param, constraint) | {
343- ( param. name . as_str ( ) , & * * constraint, None )
344- } ) ,
345- ) ;
346- }
347- }
289+ self . suggest_adding_copy_bounds ( & mut err, ty, span) ;
348290
349291 let span = if let Some ( local) = place. as_local ( ) {
350292 Some ( self . body . local_decls [ local] . source_info . span )
@@ -450,6 +392,69 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
450392 true
451393 }
452394
395+ fn suggest_adding_copy_bounds (
396+ & self ,
397+ err : & mut DiagnosticBuilder < ' tcx , ErrorGuaranteed > ,
398+ ty : Ty < ' tcx > ,
399+ span : Span ,
400+ ) {
401+ let tcx = self . infcx . tcx ;
402+ let generics = tcx. generics_of ( self . mir_def_id ( ) ) ;
403+
404+ let Some ( hir_generics) = tcx
405+ . typeck_root_def_id ( self . mir_def_id ( ) . to_def_id ( ) )
406+ . as_local ( )
407+ . and_then ( |def_id| tcx. hir ( ) . get_generics ( def_id) )
408+ else { return ; } ;
409+ // Try to find predicates on *generic params* that would allow copying `ty`
410+ let predicates: Result < Vec < _ > , _ > = tcx. infer_ctxt ( ) . enter ( |infcx| {
411+ let mut fulfill_cx = <dyn rustc_infer:: traits:: TraitEngine < ' _ > >:: new ( infcx. tcx ) ;
412+
413+ let copy_did = infcx. tcx . lang_items ( ) . copy_trait ( ) . unwrap ( ) ;
414+ let cause = ObligationCause :: new (
415+ span,
416+ self . mir_hir_id ( ) ,
417+ rustc_infer:: traits:: ObligationCauseCode :: MiscObligation ,
418+ ) ;
419+ fulfill_cx. register_bound (
420+ & infcx,
421+ self . param_env ,
422+ // Erase any region vids from the type, which may not be resolved
423+ infcx. tcx . erase_regions ( ty) ,
424+ copy_did,
425+ cause,
426+ ) ;
427+ // Select all, including ambiguous predicates
428+ let errors = fulfill_cx. select_all_or_error ( & infcx) ;
429+
430+ // Only emit suggestion if all required predicates are on generic
431+ errors
432+ . into_iter ( )
433+ . map ( |err| match err. obligation . predicate . kind ( ) . skip_binder ( ) {
434+ PredicateKind :: Trait ( predicate) => match predicate. self_ty ( ) . kind ( ) {
435+ ty:: Param ( param_ty) => Ok ( (
436+ generics. type_param ( param_ty, tcx) ,
437+ predicate. trait_ref . print_only_trait_path ( ) . to_string ( ) ,
438+ ) ) ,
439+ _ => Err ( ( ) ) ,
440+ } ,
441+ _ => Err ( ( ) ) ,
442+ } )
443+ . collect ( )
444+ } ) ;
445+
446+ if let Ok ( predicates) = predicates {
447+ suggest_constraining_type_params (
448+ tcx,
449+ hir_generics,
450+ err,
451+ predicates
452+ . iter ( )
453+ . map ( |( param, constraint) | ( param. name . as_str ( ) , & * * constraint, None ) ) ,
454+ ) ;
455+ }
456+ }
457+
453458 pub ( crate ) fn report_move_out_while_borrowed (
454459 & mut self ,
455460 location : Location ,
0 commit comments