@@ -409,6 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409409            err. downgrade_to_delayed_bug ( ) ; 
410410        } 
411411
412+         self . find_builder_fn ( & mut  err,  rcvr_ty,  source) ; 
412413        if  tcx. ty_is_opaque_future ( rcvr_ty)  && item_name. name  == sym:: poll { 
413414            err. help ( format ! ( 
414415                "method `poll` found on `Pin<&mut {ty_str}>`, \  
@@ -1407,6 +1408,93 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14071408        } 
14081409    } 
14091410
1411+     /// Look at all the associated functions without receivers in the type's inherent impls 
1412+ /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`. 
1413+ fn  find_builder_fn ( & self ,  err :  & mut  Diagnostic ,  rcvr_ty :  Ty < ' tcx > ,  source :  SelfSource < ' tcx > )  { 
1414+         let  ty:: Adt ( adt_def,  _)  = rcvr_ty. kind ( )  else  { 
1415+             return ; 
1416+         } ; 
1417+         let  SelfSource :: QPath ( ty)  = source else  { 
1418+             return ; 
1419+         } ; 
1420+         let  hir = self . tcx . hir ( ) ; 
1421+         if  let  Some ( Node :: Pat ( _) )  = hir. find ( hir. parent_id ( ty. hir_id ) )  { 
1422+             // Do not suggest a fn call when a pattern is expected. 
1423+             return ; 
1424+         } 
1425+         let  mut  items = self 
1426+             . tcx 
1427+             . inherent_impls ( adt_def. did ( ) ) 
1428+             . iter ( ) 
1429+             . flat_map ( |i| self . tcx . associated_items ( i) . in_definition_order ( ) ) 
1430+             // Only assoc fn with no receivers. 
1431+             . filter ( |item| matches ! ( item. kind,  ty:: AssocKind :: Fn )  && !item. fn_has_self_parameter ) 
1432+             . filter_map ( |item| { 
1433+                 // Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`. 
1434+                 let  ret_ty = self . tcx . fn_sig ( item. def_id ) . skip_binder ( ) . output ( ) ; 
1435+                 let  ret_ty = self . tcx . erase_late_bound_regions ( ret_ty) ; 
1436+                 let  ty:: Adt ( def,  args)  = ret_ty. kind ( )  else  { 
1437+                     return  None ; 
1438+                 } ; 
1439+                 // Check for `-> Self` 
1440+                 if  self . can_eq ( self . param_env ,  ret_ty,  rcvr_ty)  { 
1441+                     return  Some ( ( item. def_id ,  ret_ty) ) ; 
1442+                 } 
1443+                 // Check for `-> Option<Self>` or `-> Result<Self, _>` 
1444+                 if  ![ self . tcx . lang_items ( ) . option_type ( ) ,  self . tcx . get_diagnostic_item ( sym:: Result ) ] 
1445+                     . contains ( & Some ( def. did ( ) ) ) 
1446+                 { 
1447+                     return  None ; 
1448+                 } 
1449+                 let  arg = args. get ( 0 ) ?. expect_ty ( ) ; 
1450+                 if  self . can_eq ( self . param_env ,  rcvr_ty,  arg)  { 
1451+                     Some ( ( item. def_id ,  ret_ty) ) 
1452+                 }  else  { 
1453+                     None 
1454+                 } 
1455+             } ) 
1456+             . collect :: < Vec < _ > > ( ) ; 
1457+         let  post = if  items. len ( )  > 5  { 
1458+             let  items_len = items. len ( ) ; 
1459+             items. truncate ( 4 ) ; 
1460+             format ! ( "\n and {} others" ,  items_len - 4 ) 
1461+         }  else  { 
1462+             String :: new ( ) 
1463+         } ; 
1464+         match  & items[ ..]  { 
1465+             [ ]  => { } 
1466+             [ ( def_id,  ret_ty) ]  => { 
1467+                 err. span_note ( 
1468+                     self . tcx . def_span ( def_id) , 
1469+                     format ! ( 
1470+                         "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \  
1471+ , 
1472+                         self . tcx. def_path_str( def_id) , 
1473+                     ) , 
1474+                 ) ; 
1475+             } 
1476+             _ => { 
1477+                 let  span:  MultiSpan  = items
1478+                     . iter ( ) 
1479+                     . map ( |( def_id,  _) | self . tcx . def_span ( def_id) ) 
1480+                     . collect :: < Vec < Span > > ( ) 
1481+                     . into ( ) ; 
1482+                 err. span_note ( 
1483+                     span, 
1484+                     format ! ( 
1485+                         "if you're trying to build a new `{rcvr_ty}` consider using one of the \  
1486+ \n {}{post}", 
1487+                         items
1488+                             . iter( ) 
1489+                             . map( |( def_id,  _ret_ty) | self . tcx. def_path_str( def_id) ) 
1490+                             . collect:: <Vec <String >>( ) 
1491+                             . join( "\n " ) 
1492+                     ) , 
1493+                 ) ; 
1494+             } 
1495+         } 
1496+     } 
1497+ 
14101498    /// Suggest calling `Ty::method` if `.method()` isn't found because the method 
14111499/// doesn't take a `self` receiver. 
14121500fn  suggest_associated_call_syntax ( 
0 commit comments