@@ -94,6 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9494 self . suggest_method_call_on_range_literal ( err, expr, expr_ty, expected) ;
9595 self . suggest_return_binding_for_missing_tail_expr ( err, expr, expr_ty, expected) ;
9696 self . note_wrong_return_ty_due_to_generic_arg ( err, expr, expr_ty) ;
97+ self . note_fn_method_def_due_to_call ( err, expr, expected) ;
9798 }
9899
99100 /// Really hacky heuristic to remap an `assert_eq!` error to the user
@@ -1170,6 +1171,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11701171 _ => return ,
11711172 }
11721173 }
1174+
1175+ fn note_fn_method_def_due_to_call (
1176+ & self ,
1177+ err : & mut Diagnostic ,
1178+ expr : & hir:: Expr < ' _ > ,
1179+ expected : Ty < ' _ > ,
1180+ ) {
1181+ let ( def_id, ident, callee_str) = if let hir:: ExprKind :: Call ( fun, _) = expr. kind
1182+ && let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = fun. kind
1183+ && let hir:: def:: Res :: Def ( def_kind, def_id) = path. res
1184+ && !matches ! ( def_kind, hir:: def:: DefKind :: Ctor ( ..) )
1185+ {
1186+ ( def_id, path. segments [ 0 ] . ident , "function" )
1187+ } else if let hir:: ExprKind :: MethodCall ( method, ..) = expr. kind
1188+ && let Some ( def_id) = self . typeck_results . borrow ( ) . type_dependent_def_id ( expr. hir_id )
1189+ && !matches ! ( self . tcx. def_kind( def_id) , hir:: def:: DefKind :: Ctor ( ..) )
1190+ {
1191+ ( def_id, method. ident , "method" )
1192+ } else {
1193+ return ;
1194+ } ;
1195+ err. span_note (
1196+ self . tcx . def_span ( def_id) ,
1197+ format ! ( "the {callee_str} {ident} is defined here" ) ,
1198+ ) ;
1199+
1200+ if let Some ( local_did) = def_id. as_local ( )
1201+ && let Some ( node) = self . tcx . opt_hir_node ( self . tcx . local_def_id_to_hir_id ( local_did) )
1202+ && let hir:: Node :: TraitItem ( hir:: TraitItem {
1203+ kind : hir:: TraitItemKind :: Fn ( sig, ..) ,
1204+ ..
1205+ } )
1206+ | hir:: Node :: ImplItem ( hir:: ImplItem {
1207+ kind : hir:: ImplItemKind :: Fn ( sig, ..) , ..
1208+ } )
1209+ | hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Fn ( sig, ..) , .. } ) = node
1210+ && let ret_span = sig. decl . output . span ( )
1211+ && !ret_span. from_expansion ( )
1212+ && expected. has_concrete_skeleton ( )
1213+ {
1214+ let sugg =
1215+ if ret_span. is_empty ( ) { format ! ( "-> {expected}" ) } else { format ! ( "{expected}" ) } ;
1216+ err. span_suggestion (
1217+ ret_span,
1218+ format ! ( "consider changing {ident}'s return type" ) ,
1219+ sugg,
1220+ Applicability :: MaybeIncorrect ,
1221+ ) ;
1222+ }
1223+ }
11731224}
11741225
11751226pub enum TypeMismatchSource < ' tcx > {
0 commit comments