improve type mismatch error for functions

This also fixes the argument names in `report_closure_arg_mismatch`
(confusing expected/found)
This commit is contained in:
Maybe Waffle 2022-07-28 17:29:47 +04:00
parent 96b9bb4620
commit 620b0f1935

View File

@ -20,6 +20,7 @@
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::hir::map; use rustc_middle::hir::map;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
@ -253,8 +254,8 @@ fn report_closure_arg_mismatch(
&self, &self,
span: Span, span: Span,
found_span: Option<Span>, found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>; ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
fn suggest_fully_qualified_path( fn suggest_fully_qualified_path(
@ -1529,13 +1530,13 @@ fn report_closure_arg_mismatch(
&self, &self,
span: Span, span: Span,
found_span: Option<Span>, found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>, found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_string<'tcx>( pub(crate) fn build_fn_sig_ty<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> String { ) -> Ty<'tcx> {
let inputs = trait_ref.skip_binder().substs.type_at(1); let inputs = trait_ref.skip_binder().substs.type_at(1);
let sig = match inputs.kind() { let sig = match inputs.kind() {
ty::Tuple(inputs) ty::Tuple(inputs)
@ -1557,10 +1558,11 @@ pub(crate) fn build_fn_sig_string<'tcx>(
abi::Abi::Rust, abi::Abi::Rust,
), ),
}; };
trait_ref.rebind(sig).to_string()
tcx.mk_fn_ptr(trait_ref.rebind(sig))
} }
let argument_kind = match expected_ref.skip_binder().self_ty().kind() { let argument_kind = match expected.skip_binder().self_ty().kind() {
ty::Closure(..) => "closure", ty::Closure(..) => "closure",
ty::Generator(..) => "generator", ty::Generator(..) => "generator",
_ => "function", _ => "function",
@ -1569,17 +1571,22 @@ pub(crate) fn build_fn_sig_string<'tcx>(
self.tcx.sess, self.tcx.sess,
span, span,
E0631, E0631,
"type mismatch in {} arguments", "type mismatch in {argument_kind} arguments",
argument_kind
); );
let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found)); err.span_label(span, "expected due to this");
err.span_label(span, found_str);
let found_span = found_span.unwrap_or(span); let found_span = found_span.unwrap_or(span);
let expected_str = err.span_label(found_span, "found signature defined here");
format!("found signature of `{}`", build_fn_sig_string(self.tcx, expected_ref));
err.span_label(found_span, expected_str); let expected = build_fn_sig_ty(self.tcx, expected);
let found = build_fn_sig_ty(self.tcx, found);
let (expected_str, found_str) =
self.tcx.infer_ctxt().enter(|infcx| infcx.cmp(expected, found));
let signature_kind = format!("{argument_kind} signature");
err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
err err
} }