@@ -94,6 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
94
94
self . suggest_method_call_on_range_literal ( err, expr, expr_ty, expected) ;
95
95
self . suggest_return_binding_for_missing_tail_expr ( err, expr, expr_ty, expected) ;
96
96
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) ;
97
98
}
98
99
99
100
/// Really hacky heuristic to remap an `assert_eq!` error to the user
@@ -1170,6 +1171,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1170
1171
_ => return ,
1171
1172
}
1172
1173
}
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
+ }
1173
1224
}
1174
1225
1175
1226
pub enum TypeMismatchSource < ' tcx > {
0 commit comments