@@ -3709,7 +3709,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37093709 self . consider_hint_about_removing_semicolon ( blk, expected_ty, err) ;
37103710 }
37113711 if let Some ( fn_span) = fn_span {
3712- err. span_label ( fn_span, "this function's body doesn't return" ) ;
3712+ err. span_label (
3713+ fn_span,
3714+ "implicitly returns `()` as its body has no tail or `return` \
3715+ expression",
3716+ ) ;
37133717 }
37143718 } , false ) ;
37153719 }
@@ -3819,6 +3823,101 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38193823 pointing_at_return_type
38203824 }
38213825
3826+ /// When encountering an fn-like ctor that needs to unify with a value, check whether calling
3827+ /// the ctor would successfully solve the type mismatch and if so, suggest it:
3828+ /// ```
3829+ /// fn foo(x: usize) -> usize { x }
3830+ /// let x: usize = foo; // suggest calling the `foo` function: `foo(42)`
3831+ /// ```
3832+ fn suggest_fn_call (
3833+ & self ,
3834+ err : & mut DiagnosticBuilder < ' tcx > ,
3835+ expr : & hir:: Expr ,
3836+ expected : Ty < ' tcx > ,
3837+ found : Ty < ' tcx > ,
3838+ ) -> bool {
3839+ match found. sty {
3840+ ty:: FnDef ( ..) | ty:: FnPtr ( _) => { }
3841+ _ => return false ,
3842+ }
3843+ let hir = self . tcx . hir ( ) ;
3844+
3845+ let sig = found. fn_sig ( self . tcx ) ;
3846+ let sig = self
3847+ . replace_bound_vars_with_fresh_vars ( expr. span , infer:: FnCall , & sig)
3848+ . 0 ;
3849+ let sig = self . normalize_associated_types_in ( expr. span , & sig) ;
3850+ if let Ok ( _) = self . try_coerce ( expr, sig. output ( ) , expected, AllowTwoPhase :: No ) {
3851+ let ( mut sugg_call, applicability) = if sig. inputs ( ) . is_empty ( ) {
3852+ ( String :: new ( ) , Applicability :: MachineApplicable )
3853+ } else {
3854+ ( "..." . to_string ( ) , Applicability :: HasPlaceholders )
3855+ } ;
3856+ let mut msg = "call this function" ;
3857+ if let ty:: FnDef ( def_id, ..) = found. sty {
3858+ match hir. get_if_local ( def_id) {
3859+ Some ( Node :: Item ( hir:: Item {
3860+ node : ItemKind :: Fn ( .., body_id) ,
3861+ ..
3862+ } ) ) |
3863+ Some ( Node :: ImplItem ( hir:: ImplItem {
3864+ node : hir:: ImplItemKind :: Method ( _, body_id) ,
3865+ ..
3866+ } ) ) |
3867+ Some ( Node :: TraitItem ( hir:: TraitItem {
3868+ node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Provided ( body_id) ) ,
3869+ ..
3870+ } ) ) => {
3871+ let body = hir. body ( * body_id) ;
3872+ sugg_call = body. arguments . iter ( )
3873+ . map ( |arg| match & arg. pat . node {
3874+ hir:: PatKind :: Binding ( _, _, ident, None )
3875+ if ident. name != kw:: SelfLower => ident. to_string ( ) ,
3876+ _ => "_" . to_string ( ) ,
3877+ } ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3878+ }
3879+ Some ( Node :: Ctor ( hir:: VariantData :: Tuple ( fields, _) ) ) => {
3880+ sugg_call = fields. iter ( ) . map ( |_| "_" ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
3881+ match hir. as_local_hir_id ( def_id) . and_then ( |hir_id| hir. def_kind ( hir_id) ) {
3882+ Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , _) ) => {
3883+ msg = "instantiate this tuple variant" ;
3884+ }
3885+ Some ( hir:: def:: DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , _) ) => {
3886+ msg = "instantiate this tuple struct" ;
3887+ }
3888+ _ => { }
3889+ }
3890+ }
3891+ Some ( Node :: ForeignItem ( hir:: ForeignItem {
3892+ node : hir:: ForeignItemKind :: Fn ( _, idents, _) ,
3893+ ..
3894+ } ) ) |
3895+ Some ( Node :: TraitItem ( hir:: TraitItem {
3896+ node : hir:: TraitItemKind :: Method ( .., hir:: TraitMethod :: Required ( idents) ) ,
3897+ ..
3898+ } ) ) => sugg_call = idents. iter ( )
3899+ . map ( |ident| if ident. name != kw:: SelfLower {
3900+ ident. to_string ( )
3901+ } else {
3902+ "_" . to_string ( )
3903+ } ) . collect :: < Vec < _ > > ( )
3904+ . join ( ", " ) ,
3905+ _ => { }
3906+ }
3907+ } ;
3908+ if let Ok ( code) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
3909+ err. span_suggestion (
3910+ expr. span ,
3911+ & format ! ( "use parentheses to {}" , msg) ,
3912+ format ! ( "{}({})" , code, sugg_call) ,
3913+ applicability,
3914+ ) ;
3915+ return true ;
3916+ }
3917+ }
3918+ false
3919+ }
3920+
38223921 pub fn suggest_ref_or_into (
38233922 & self ,
38243923 err : & mut DiagnosticBuilder < ' tcx > ,
@@ -3833,6 +3932,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38333932 suggestion,
38343933 Applicability :: MachineApplicable ,
38353934 ) ;
3935+ } else if let ( ty:: FnDef ( def_id, ..) , true ) = (
3936+ & found. sty ,
3937+ self . suggest_fn_call ( err, expr, expected, found) ,
3938+ ) {
3939+ if let Some ( sp) = self . tcx . hir ( ) . span_if_local ( * def_id) {
3940+ let sp = self . sess ( ) . source_map ( ) . def_span ( sp) ;
3941+ err. span_label ( sp, & format ! ( "{} defined here" , found) ) ;
3942+ }
38363943 } else if !self . check_for_cast ( err, expr, found, expected) {
38373944 let is_struct_pat_shorthand_field = self . is_hir_id_from_struct_pattern_shorthand_field (
38383945 expr. hir_id ,
0 commit comments