diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-07-30 20:39:47 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-30 20:39:47 +0530 |
| commit | eb378d2015d10b6b99955512ab005665f417e014 (patch) | |
| tree | a127271a4e8d242b84f55cebf51d801bc3695e5c /compiler/rustc_trait_selection/src | |
| parent | c668820365bc9c66408b993cda84d48532a9e0ce (diff) | |
| parent | 7da578b8f818cef1957502298f30ff10729278b5 (diff) | |
| download | rust-eb378d2015d10b6b99955512ab005665f417e014.tar.gz rust-eb378d2015d10b6b99955512ab005665f417e014.zip | |
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`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 05a8754af81..b2eb8fdf8a5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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 } |
