Rollup merge of #99862 - WaffleLapkin:type_mismatch_fix, r=compiler-errors
Improve type mismatch w/ function signatures This PR makes use of `note: expected/found` (instead of labeling types in labels) in type mismatch with function signatures. Pros: it's easier to compare the signatures, cons: the error is a little more verbose now. This is especially nice when - The signatures differ in a small subset of parameters (same parameters are elided) - The difference is in details, for example `isize` vs `usize` (there is a better chance that the types align) Also this PR fixes the inconsistency in variable names in the edited code (`expected` and `found`). A zulip thread from which this pr started: [[link]](https://rust-lang.zulipchat.com/#narrow/stream/147480-t-compiler.2Fwg-diagnostics/topic/Type.20error.20regression.3F.2E.2E.2E/near/289756602). An example diagnostic: <table> <tr> <th>this pr</th> <th>nightly</th> </tr> <tr> <td> ```text error[E0631]: type mismatch in function arguments --> ./t.rs:4:12 | 4 | expect(&f); | ------ ^^ expected due to this | | | required by a bound introduced by this call ... 10 | fn f(_: isize, _: u8, _: Vec<u32>) {} | ---------------------------------- found signature defined here | = note: expected function signature `fn(usize, _, Vec<u64>) -> _` found function signature `fn(isize, _, Vec<u32>) -> _` note: required because of the requirements on the impl of `Trait` for `fn(isize, u8, Vec<u32>) {f}` --> ./t.rs:8:9 | 8 | impl<F> Trait for F where F: Fn(usize, u8, Vec<u64>) -> u8 {} | ^^^^^ ^ = note: required for the cast from `fn(isize, u8, Vec<u32>) {f}` to the object type `dyn Trait` ``` </td> <td> ```text error[E0631]: type mismatch in function arguments --> ./t.rs:4:12 | 4 | expect(&f); | ------ ^^ expected signature of `fn(usize, u8, Vec<u64>) -> _` | | | required by a bound introduced by this call ... 10 | fn f(_: isize, _: u8, _: Vec<u32>) {} | ---------------------------------- found signature of `fn(isize, u8, Vec<u32>) -> _` | note: required because of the requirements on the impl of `Trait` for `fn(isize, u8, Vec<u32>) {f}` --> ./t.rs:8:9 | 8 | impl<F> Trait for F where F: Fn(usize, u8, Vec<u64>) -> u8 {} | ^^^^^ ^ = note: required for the cast to the object type `dyn Trait` ``` </td> </tr> </table> <details><summary>code</summary> <p> ```rust fn main() { fn expect(_: &dyn Trait) {} expect(&f); } trait Trait {} impl<F> Trait for F where F: Fn(usize, u8, Vec<u64>) -> u8 {} fn f(_: isize, _: u8, _: Vec<u32>) {} ``` </p> </details> r? `@compiler-errors`
This commit is contained in:
commit
eb378d2015
13 changed files with 139 additions and 76 deletions
|
@ -20,6 +20,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::hir::map;
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
|
||||
|
@ -253,8 +254,8 @@ pub trait InferCtxtExt<'tcx> {
|
|||
&self,
|
||||
span: Span,
|
||||
found_span: Option<Span>,
|
||||
expected_ref: ty::PolyTraitRef<'tcx>,
|
||||
found: ty::PolyTraitRef<'tcx>,
|
||||
expected: ty::PolyTraitRef<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
fn suggest_fully_qualified_path(
|
||||
|
@ -1536,13 +1537,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
span: Span,
|
||||
found_span: Option<Span>,
|
||||
expected_ref: ty::PolyTraitRef<'tcx>,
|
||||
found: ty::PolyTraitRef<'tcx>,
|
||||
expected: ty::PolyTraitRef<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
pub(crate) fn build_fn_sig_string<'tcx>(
|
||||
pub(crate) fn build_fn_sig_ty<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> String {
|
||||
) -> Ty<'tcx> {
|
||||
let inputs = trait_ref.skip_binder().substs.type_at(1);
|
||||
let sig = match inputs.kind() {
|
||||
ty::Tuple(inputs)
|
||||
|
@ -1564,10 +1565,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
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::Generator(..) => "generator",
|
||||
_ => "function",
|
||||
|
@ -1576,17 +1578,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
self.tcx.sess,
|
||||
span,
|
||||
E0631,
|
||||
"type mismatch in {} arguments",
|
||||
argument_kind
|
||||
"type mismatch in {argument_kind} arguments",
|
||||
);
|
||||
|
||||
let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found));
|
||||
err.span_label(span, found_str);
|
||||
err.span_label(span, "expected due to this");
|
||||
|
||||
let found_span = found_span.unwrap_or(span);
|
||||
let expected_str =
|
||||
format!("found signature of `{}`", build_fn_sig_string(self.tcx, expected_ref));
|
||||
err.span_label(found_span, expected_str);
|
||||
err.span_label(found_span, "found signature defined here");
|
||||
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue