@@ -292,44 +292,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
292292 . as_local ( )
293293 . and_then ( |def_id| tcx. hir ( ) . get_generics ( def_id) )
294294 {
295- let predicates: Result < Vec < _ > , _ > = tcx. infer_ctxt ( ) . enter ( |infcx| {
296- let mut fulfill_cx =
297- <dyn rustc_infer:: traits:: TraitEngine < ' _ > >:: new ( infcx. tcx ) ;
298-
299- let copy_did = infcx. tcx . lang_items ( ) . copy_trait ( ) . unwrap ( ) ;
300- let cause = ObligationCause :: new (
301- span,
302- self . mir_hir_id ( ) ,
303- rustc_infer:: traits:: ObligationCauseCode :: MiscObligation ,
304- ) ;
305- fulfill_cx. register_bound (
306- & infcx,
307- self . param_env ,
308- // Erase any region vids from the type, which may not be resolved
309- infcx. tcx . erase_regions ( ty) ,
310- copy_did,
311- cause,
312- ) ;
313- // Select all, including ambiguous predicates
314- let errors = fulfill_cx. select_all_or_error ( & infcx) ;
315-
316- // Only emit suggestion if all required predicates are on generic
317- errors
318- . into_iter ( )
319- . map ( |err| match err. obligation . predicate . kind ( ) . skip_binder ( ) {
320- PredicateKind :: Trait ( predicate) => {
321- match predicate. self_ty ( ) . kind ( ) {
322- ty:: Param ( param_ty) => Ok ( (
323- generics. type_param ( param_ty, tcx) ,
324- predicate. trait_ref . print_only_trait_path ( ) . to_string ( ) ,
325- ) ) ,
326- _ => Err ( ( ) ) ,
327- }
328- }
329- _ => Err ( ( ) ) ,
330- } )
331- . collect ( )
332- } ) ;
295+ let copy_did = tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ;
296+ let predicates =
297+ self . try_find_missing_generic_bounds ( ty, copy_did, generics, span) ;
333298
334299 if let Ok ( predicates) = predicates {
335300 suggest_constraining_type_params (
@@ -2256,6 +2221,53 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
22562221 }
22572222 }
22582223 }
2224+
2225+ /// Tries to find bounds on `generics` that satisfy `ty: required_trait_did` bound.
2226+ fn try_find_missing_generic_bounds (
2227+ & self ,
2228+ ty : Ty < ' tcx > ,
2229+ required_trait_did : DefId ,
2230+ generics : & ' tcx ty:: Generics ,
2231+ obligation_cause_span : Span ,
2232+ ) -> Result < Vec < ( & ' tcx ty:: GenericParamDef , String ) > , ( ) > {
2233+ let tcx = self . infcx . tcx ;
2234+ let predicates: Result < Vec < _ > , _ > = tcx. infer_ctxt ( ) . enter ( |infcx| {
2235+ let mut fulfill_cx = <dyn rustc_infer:: traits:: TraitEngine < ' _ > >:: new ( infcx. tcx ) ;
2236+
2237+ let cause = ObligationCause :: new (
2238+ obligation_cause_span,
2239+ self . mir_hir_id ( ) ,
2240+ rustc_infer:: traits:: ObligationCauseCode :: MiscObligation ,
2241+ ) ;
2242+ fulfill_cx. register_bound (
2243+ & infcx,
2244+ self . param_env ,
2245+ // Erase any region vids from the type, which may not be resolved
2246+ infcx. tcx . erase_regions ( ty) ,
2247+ required_trait_did,
2248+ cause,
2249+ ) ;
2250+ // Select all, including ambiguous predicates
2251+ let errors = fulfill_cx. select_all_or_error ( & infcx) ;
2252+
2253+ // Only emit suggestion if all required predicates are on generic
2254+ errors
2255+ . into_iter ( )
2256+ . map ( |err| match err. obligation . predicate . kind ( ) . skip_binder ( ) {
2257+ PredicateKind :: Trait ( predicate) => match predicate. self_ty ( ) . kind ( ) {
2258+ ty:: Param ( param_ty) => Ok ( (
2259+ generics. type_param ( param_ty, tcx) ,
2260+ predicate. trait_ref . print_only_trait_path ( ) . to_string ( ) ,
2261+ ) ) ,
2262+ _ => Err ( ( ) ) ,
2263+ } ,
2264+ _ => Err ( ( ) ) ,
2265+ } )
2266+ . collect ( )
2267+ } ) ;
2268+
2269+ predicates
2270+ }
22592271}
22602272
22612273#[ derive( Debug ) ]
0 commit comments