Uh oh!
There was an error while loading. Please reload this page.
Friendlier error message for closure argument type mismatch - #44735
Conversation
rust-highfive
commented
Sep 21, 2017
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @nikomatsakis (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
There was a problem hiding this comment.
You're still matching against the expected/found, which could lead to this bogusly triggering when one of the arguments is a tuple - when you have something like fn((u32, u32)): Fn((u32,)).
There's no reason to do so - you have the trait-refs in expected_trait_ref and actual_trait_ref.
You can get the argument length of each argument in this way:
// skipping the binder is ok because we only care if this is a tuplelet arg_len = matchX_trait_ref.skip_binder().substs.type_at(1){
ty::TyTuple(ref tys) => Some(tys.len()),
_ => None};
tirr-c
left a comment
There was a problem hiding this comment.
I have a few questions. I've contributed to Rust a little, but still not sure how to write compiler code...
There was a problem hiding this comment.
Is this code unreachable? I mean, will report_closure_arg_mismatch be called even when one of the Fn traits has zero arguments?
There was a problem hiding this comment.
Why aren't you calling report_type_argument_mismatch?
There was a problem hiding this comment.
I think you won't see this error message - no arguments, no place for a type error.
There was a problem hiding this comment.
Is it fine to use standard panic macro like panic! or unreachable! to signal compiler bugs? (panic! here is a mistake, I should have used unreachable! here)
There was a problem hiding this comment.
An unreachable!() is ok-ish for local things, but it is recommended to use bug! or span_bug!(span, "error") - span_bug also displays the span of the error, which makes for easier debugging.
There was a problem hiding this comment.
You should display the "takes" even when you don't have a span - aka fn pointers:
fnfoo(f:fn((u32,u32))){
a.iter().map(f)}There was a problem hiding this comment.
I think you should add a test for each case with fn pointer - arg count mismatch, same arg count but type-error, higher-ranked error, F: Fn<u32> bad bound.
There was a problem hiding this comment.
Higher-ranked test for fn pointers:
fnfoo<F:Fn(*mut&u32)>(_f:F){}fnbar<'a>(f:fn(*mut&'au32)){foo(f);}Higher-ranked test for closures: src/test/ui/mismatched_types/closure-mismatch.rs (already exists)
Just check that the error message is sane.
There was a problem hiding this comment.
With respect to the span specifically, probably just something like this would be fine:
let found_span = found_span.unwrap_or(span);
i.e., if we don't have a better span, display both messages at the same place.
nikomatsakis
commented
Sep 21, 2017
@tirr-c this looks awesome btw! |
Tried @arielb1's test code, and I get two errors. #![feature(unboxed_closures)]fnmain(){}fnfoo<F:Fn(*mut&u32)>(_f:F){}fnbar<'a>(f:fn(*mut&'au32)){foo(f);}(ignore Is this okay? |
Your error message says "closure" for the function pointer. You should make it say "function" (you can use |
arielb1
commented
Sep 21, 2017
Other than that the error messages look sane. Just be sure to add a UI test so I can see them before giving the r+. Otherwise LGTM. |
tirr-c
commented
Sep 21, 2017
I've removed the test |
There was a problem hiding this comment.
If E0281 still exists, please write a test that reproduces it. That's the Fn<usize> test.
There was a problem hiding this comment.
This erases the binder. I don't like this error message.
There was a problem hiding this comment.
@arielb1 the expected and found signatures are in the labels now, I'm not sure if that was the case when you left this comment.
arielb1
commented
Sep 21, 2017
Please add the test for E0281 back - all error codes are supposed to have a test for them, and you can similarly add a test for E0631 with the name |
arielb1
commented
Sep 21, 2017
there's another doctest for E0281 in rust/src/librustc/diagnostics.rs Line 1141 in 1b55d19 |
nikomatsakis
commented
Sep 21, 2017
r? @arielb1 |
tirr-c
commented
Sep 21, 2017
Should pass the test, but the documentation needs to be rewritten now I think... |
arielb1
commented
Sep 21, 2017
now you just need to use |
tirr-c
commented
Sep 22, 2017
|
tirr-c
commented
Sep 22, 2017
Error message from the test for Before: After: |
tirr-c
commented
Sep 22, 2017
E0281, the original error code, is totally replaced by E0631. I left E0281 in the error code index, though. |
bors
commented
Sep 22, 2017
☔ The latest upstream changes (presumably #44691) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
Nit: we should enclose the signature in backticks:
+ | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
Fixesrust-lang#42143. E0281 is totally replaced by E0631. UI tests are updated accordingly.
arielb1
commented
Sep 24, 2017
That's cool. @bors r+ |
bors
commented
Sep 24, 2017
📌 Commit 1bfbfb2 has been approved by |
bors
commented
Sep 26, 2017
Friendlier error message for closure argument type mismatch Rebased #42270. Fixes#42143. --- `test.rs`: ```rust fn main() { foo(|_: i32, _: usize| ()); } fn foo<F>(_: F) where F: Fn(&str, usize) {} ``` Before: ``` error[E0281]: type mismatch: `[closure@test.rs:2:9: 2:30]` implements the trait `std::ops::Fn<(i32, usize)>`, but the trait `for<'r> std::ops::Fn<(&'r str, usize)>` is required --> test.rs:2:5 | 2 | foo(|_: i32, _: usize| ()); | ^^^ --------------------- implements `std::ops::Fn<(i32, usize)>` | | | expected &str, found i32 | requires `for<'r> std::ops::Fn<(&'r str, usize)>` | = note: required by `foo` ``` After (early): ``` error[E0631]: type mismatch in closure arguments --> test.rs:2:5 | 2 | foo(|_: i32, _: usize| ()); | ^^^ --------------------- takes arguments of type `i32` and `usize` | | | expected arguments of type `&str` and `usize` | = note: required by `foo` ``` After (current): ``` error[E0631]: type mismatch in closure arguments --> test.rs:2:5 | 2 | foo(|_: i32, _: usize| ()); | ^^^ --------------------- found signature of `fn(i32, usize) -> _` | | | expected signature of `for<'r> fn(&'r str, usize) -> _` | = note: required by `foo` ``` ~~Compiler output has been changed, and a few tests are failing. Help me writing/fixing tests!~~ r? @nikomatsakis
bors
commented
Sep 26, 2017
☀️ Test successful - status-appveyor, status-travis |
Rebased #42270.
Fixes#42143.
test.rs:Before:
After (early):
After (current):
Compiler output has been changed, and a few tests are failing. Help me writing/fixing tests!r? @nikomatsakis