Skip to content

Commit ec037a4

Browse files
committed
Point at fn definition on type mismatch involving call
1 parent f8fe517 commit ec037a4

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+51
Original file line numberDiff line numberDiff line change
@@ -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

11751226
pub enum TypeMismatchSource<'tcx> {

0 commit comments

Comments
 (0)