Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upFriendlier error message for closure argument type mismatch #44735
Conversation
rust-highfive
assigned
nikomatsakis
Sep 21, 2017
This comment has been minimized.
This comment has been minimized.
|
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. |
arielb1
reviewed
Sep 21, 2017
| @@ -730,40 +730,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { | |||
| expected_found.found, | |||
| expected_trait_ty.is_closure()) | |||
| } else if let &TypeError::Sorts(ref expected_found) = e { | |||
| let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty { | |||
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
•
Contributor
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 tuple
let arg_len = match X_trait_ref.skip_binder().substs.type_at(1) {
ty::TyTuple(ref tys) => Some(tys.len()),
_ => None
};
tirr-c
reviewed
Sep 21, 2017
|
I have a few questions. I've contributed to Rust a little, but still not sure how to write compiler code... |
| ty::TyTuple(args, _) => { | ||
| let len = args.len(); | ||
| if len == 0 { | ||
| return String::from("no arguments"); |
This comment has been minimized.
This comment has been minimized.
tirr-c
Sep 21, 2017
Author
Contributor
Is this code unreachable? I mean, will report_closure_arg_mismatch be called even when one of the Fn traits has zero arguments?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
Contributor
I think you won't see this error message - no arguments, no place for a type error.
| if len == 1 { "" } else { "s" }, | ||
| type_list_string) | ||
| }, | ||
| _ => panic!(), |
This comment has been minimized.
This comment has been minimized.
tirr-c
Sep 21, 2017
Author
Contributor
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)
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
Contributor
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.
arielb1
reviewed
Sep 21, 2017
| move |trait_ref| build_args_type_string(span, trait_ref) | ||
| ); | ||
| err.span_label(span, format!("expected {}", found_arg_list.skip_binder())); | ||
| if let Some(sp) = found_span { |
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
Contributor
You should display the "takes" even when you don't have a span - aka fn pointers:
fn foo(f: fn((u32, u32))) {
a.iter().map(f)
}
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
•
Contributor
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.
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
Contributor
Higher-ranked test for fn pointers:
fn foo<F: Fn(*mut &u32)>(_f: F) {}
fn bar<'a>(f: fn(*mut &'a u32)) { 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.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Sep 21, 2017
Contributor
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.
This comment has been minimized.
This comment has been minimized.
|
@tirr-c this looks awesome btw! |
This comment has been minimized.
This comment has been minimized.
|
Tried @arielb1's test code, and I get two errors. #![feature(unboxed_closures)]
fn main() {}
fn foo<F: Fn(*mut &u32)>(_f: F) {}
fn bar<'a>(f: fn(*mut &'a u32)) { foo(f); }(ignore
Is this okay? |
This comment has been minimized.
This comment has been minimized.
Your error message says "closure" for the function pointer. You should make it say "function" (you can use |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
I've removed the test |
arielb1
reviewed
Sep 21, 2017
| @@ -1,25 +0,0 @@ | |||
| // Copyright 2016 The Rust Project Developers. See the COPYRIGHT | |||
This comment has been minimized.
This comment has been minimized.
arielb1
Sep 21, 2017
Contributor
If E0281 still exists, please write a test that reproduces it. That's the Fn<usize> test.
arielb1
reviewed
Sep 21, 2017
| @@ -7,14 +7,13 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r | |||
| = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` | |||
| = note: required by `baz` | |||
|
|
|||
| error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required | |||
| error[E0631]: type mismatch in closure arguments | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
estebank
Sep 22, 2017
Contributor
@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.
This comment has been minimized.
This comment has been minimized.
|
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 |
alexcrichton
added
the
S-waiting-on-review
label
Sep 21, 2017
This comment has been minimized.
This comment has been minimized.
there's another doctest for E0281 in rust/src/librustc/diagnostics.rs Line 1141 in 1b55d19 |
This comment has been minimized.
This comment has been minimized.
|
r? @arielb1 |
rust-highfive
assigned
arielb1
and unassigned
nikomatsakis
Sep 21, 2017
This comment has been minimized.
This comment has been minimized.
|
Should pass the test, but the documentation needs to be rewritten now I think... |
This comment has been minimized.
This comment has been minimized.
|
now you just need to use |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
|
Error message from the test for Before:
After:
|
This comment has been minimized.
This comment has been minimized.
E0281, the original error code, is totally replaced by E0631. I left E0281 in the error code index, though. |
tirr-c
force-pushed the
tirr-c:issue-42143
branch
from
6764934
to
135545a
Sep 22, 2017
This comment has been minimized.
This comment has been minimized.
|
|
tirr-c
force-pushed the
tirr-c:issue-42143
branch
from
135545a
to
29e5db0
Sep 22, 2017
nikomatsakis
reviewed
Sep 22, 2017
| --> $DIR/issue-36053-2.rs:17:32 | ||
| | | ||
| 17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); | ||
| | ^^^^^^ -------------- implements `for<'r> std::ops::FnMut<(&'r str,)>` | ||
| | ^^^^^^ -------------- found signature of for<'r> fn(&'r str) -> _ |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
Sep 22, 2017
Contributor
Nit: we should enclose the signature in backticks:
+ | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
tirr-c
force-pushed the
tirr-c:issue-42143
branch
from
29e5db0
to
cc56688
Sep 23, 2017
tirr-c
force-pushed the
tirr-c:issue-42143
branch
from
cc56688
to
1bfbfb2
Sep 23, 2017
This comment has been minimized.
This comment has been minimized.
|
That's cool. @bors r+ |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Sep 26, 2017
This comment has been minimized.
This comment has been minimized.
|
|
tirr-c commentedSep 21, 2017
•
edited
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