Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up callable type mismatch errors #41488

Merged
merged 4 commits into from
May 2, 2017
Merged

Conversation

estebank
Copy link
Contributor

@estebank estebank commented Apr 23, 2017

error[E0593]: closure takes 1 argument but 2 arguments are required here
  --> ../../src/test/ui/mismatched_types/closure-arg-count.rs:13:15
   |
13 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |               ^^^^^^^ -------------------------- takes 1 argument
   |               |
   |               expected closure that takes 2 arguments

instead of

error[E0281]: type mismatch: the type `[closure@../../src/test/ui/mismatched_types/closure-arg-count.rs:13:23: 13:49]` implements the trait `for<'r> std::ops::FnMut<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnMut<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
  --> ../../src/test/ui/mismatched_types/closure-arg-count.rs:13:15
   |
13 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |               ^^^^^^^

Fix #21857, re #24680.

@rust-highfive
Copy link
Collaborator

r? @eddyb

(rust_highfive has picked a reviewer for you, use r? to override)

@estebank estebank changed the title Closure args Clean up closure type mismatch errors Apr 23, 2017
@eddyb
Copy link
Member

eddyb commented Apr 24, 2017

r? @jonathandturner

@rust-highfive rust-highfive assigned sophiajt and unassigned eddyb Apr 24, 2017
e)
let expected_trait_ty = expected_trait_ref.self_ty();
if expected_trait_ty.is_closure() {
if let &TypeError::TupleSize(ref expected_found) = e {
Copy link
Contributor

@arielb1 arielb1 Apr 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you match on expected_trait_ref & actual_trait_ref, to avoid Fn(X<()>) vs. Fn(X<(Foo, Bar)>) etc.

Also, this error message is probably good for all Fn() trait users, even if they are not closures.

@leonardo-m
Copy link

This code:

#![allow(unused_variables)]
fn main() {
    [1, 2, 3].sort_by(|(x, y)| panic!());
}

Currently gives me lot of error output:

error[E0308]: mismatched types
 --> ...\test.rs:3:24
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |                        ^^^^^^ expected &{integer}, found tuple
  |
  = note: expected type `&{integer}`
             found type `(_, _)`

error[E0281]: type mismatch: the type `[closure@...\test.rs:3:23: 3:40]` implements the trait `for<'r> std::ops::FnMut<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnMut<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
 --> ...\test.rs:3:15
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |               ^^^^^^^

error[E0281]: type mismatch: the type `[closure@...\test.rs:3:23: 3:40]` implements the trait `for<'r> std::ops::FnOnce<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnOnce<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
 --> ...\test.rs:3:15
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |               ^^^^^^^

error: aborting due to 3 previous errors

A better error output could be:

error[E0593]: ../../src/test/ui/mismatched_types/closure-arg-count.rs:13:15
   |
13 |     [1, 2, 3].sort_by(|(x, y)| panic!());
   |                        ^^^^^^ -------- 1 argument given
   |                        |
   |                        expected closure that takes 2 arguments

@carols10cents carols10cents added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 24, 2017
@nagisa
Copy link
Member

nagisa commented Apr 24, 2017

Nit on wording. In definitions/declarations it is “arguments”, not “parameters”. “parameters” is for expressions that get passed into the function call.

@estebank estebank force-pushed the closure-args branch 3 times, most recently from d05bbec to ad291b7 Compare April 24, 2017 22:10
@estebank estebank changed the title Clean up closure type mismatch errors Clean up callable type mismatch errors Apr 24, 2017
@estebank
Copy link
Contributor Author

@nagisa @arielb1 done.

@sophiajt
Copy link
Contributor

@leonardo-m - did the error message get worse or stay the same? If it's the same, we could take this PR and then tackle your example as a separate issue.

foo(|y| { }); //~ ERROR E0281
//~^ ERROR E0281
foo(|y: String| { });
//~^ ERROR E0281
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to a ui test?

@@ -19,9 +19,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
fn main() {
apply(&3, takes_imm);
apply(&3, takes_mut);
//~^ ERROR (types differ in mutability)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

@@ -18,4 +18,11 @@ fn main() {
//~^ ERROR no method named `count`
//~| ERROR E0281
//~| ERROR E0281
//~| NOTE expected &str, found str
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

let z = call_it(3, f);
//~^ ERROR type mismatch
//~| ERROR type mismatch
//~| NOTE expected isize, found usize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for all.

| ^^^ expected bound lifetime parameter, found concrete lifetime
|
= note: concrete lifetime that was found is lifetime '_#0r
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two notes don't seem helplful. Are they what is there currently, rather than being added by this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already part of the current output. I would prefer to remove them in a separate (smaller) PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that's fine

@sophiajt
Copy link
Contributor

Yeah, that looks pretty good. 👍 from me.

for error in errors {
self.report_fulfillment_error(error);
// Avoid multiple errors saying the same thing for closures
Copy link
Contributor

@arielb1 arielb1 Apr 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this targeted at something specific? e.g. it would be nice if we could filter projection errors if there is a corresponding selection error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see the effect of this in the stderr output, right now for closure type mismatch errors we output two (may be three in some cases?, haven't seen that yet) after the compiler tries to coerce to Fn, FnMut and FnOnce. This change was hacky and want to fix it properly somewhere closer to the source but this is as close as I got to the culprit last night. We can either remove this hack now and merge the PR with the duplicated errors, or merge this as is and I send a follow up PR fully addressing this.

@leonardo-m
Copy link

@jonathandturner: >did the error message get worse or stay the same?

I don't fully understand your question. Given this code:

#![allow(unused_variables)]
fn main() {
    [1, 2, 3].sort_by(|(x, y)| panic!());
}

This is how its error messages have evolved:

--------------------------------
1.0:

<source>:3:24: 3:30 error: mismatched types:
 expected `&_`,
    found `(_, _)`
(expected &-ptr,
    found tuple) [E0308]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                              ^~~~~~
<source>:3:15: 3:41 error: type mismatch: the type `[closure /tmp/compiler-explorer-compiler117326-8-ixlnde.do96qrggb9/example.rs:3:23: 3:40]` implements the trait `for<'r> core::ops::FnMut<(&'r _,)>`, but the trait `for<'r,'r> core::ops::FnMut<(&'r _, &'r _)>` is required (expected a tuple with 2 elements, found one with 1 elements) [E0281]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:3:15: 3:41 error: type mismatch: the type `[closure /tmp/compiler-explorer-compiler117326-8-ixlnde.do96qrggb9/example.rs:3:23: 3:40]` implements the trait `for<'r> core::ops::FnOnce<(&'r _,)>`, but the trait `for<'r,'r> core::ops::FnOnce<(&'r _, &'r _)>` is required (expected a tuple with 2 elements, found one with 1 elements) [E0281]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 3 previous errors
Compiler exited with result code 101

--------------------------------
1.11:

<source>:3:24: 3:30 error: mismatched types [E0308]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                               ^~~~~~
<source>:3:24: 3:30 help: run `rustc --explain E0308` to see a detailed explanation
<source>:3:24: 3:30 note: expected type `&_`
<source>:3:24: 3:30 note:    found type `(_, _)`
<source>:3:15: 3:22 error: type mismatch: the type `[closure@/tmp/compiler-explorer-compiler117326-8-1ggak45.5sng6wdn29/example.rs:3:23: 3:40]` implements the trait `for<'r> std::ops::FnMut<(&'r _,)>`, but the trait `for<'r, 'r> std::ops::FnMut<(&'r _, &'r _)>` is required (expected a tuple with 2 elements, found one with 1 elements) [E0281]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                      ^~~~~~~
<source>:3:15: 3:22 help: run `rustc --explain E0281` to see a detailed explanation
<source>:3:15: 3:22 error: type mismatch: the type `[closure@/tmp/compiler-explorer-compiler117326-8-1ggak45.5sng6wdn29/example.rs:3:23: 3:40]` implements the trait `for<'r> std::ops::FnOnce<(&'r _,)>`, but the trait `for<'r, 'r> std::ops::FnOnce<(&'r _, &'r _)>` is required (expected a tuple with 2 elements, found one with 1 elements) [E0281]
<source>:3     [1, 2, 3].sort_by(|(x, y)| panic!());
                                                                                      ^~~~~~~
<source>:3:15: 3:22 help: run `rustc --explain E0281` to see a detailed explanation
error: aborting due to 3 previous errors
Compiler exited with result code 101

--------------------------------
1.12 - 1.18nightly:

error[E0308]: mismatched types
 --> <source>:3:24
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |                        ^^^^^^ expected &{integer}, found tuple
  |
  = note: expected type `&{integer}`
  = note:    found type `(_, _)`
error[E0281]: type mismatch: the type `[closure@<source>:3:23: 3:40]` implements the trait `for<'r> std::ops::FnMut<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnMut<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
 --> <source>:3:15
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |               ^^^^^^^
error[E0281]: type mismatch: the type `[closure@<source>:3:23: 3:40]` implements the trait `for<'r> std::ops::FnOnce<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnOnce<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
 --> <source>:3:15
  |
3 |     [1, 2, 3].sort_by(|(x, y)| panic!());
  |               ^^^^^^^
error: aborting due to 3 previous errors
Compiler exited with result code 101

--------------------------------

So the error messages are essentially the same. And I think they could use an improvement (the first improvement is to generate only one error message).

@estebank
Copy link
Contributor Author

@leonardo-m the output for that file with the changes on this PR is:

error[E0308]: mismatched types
  --> $DIR/closure-arg-count.rs:3:24
   |
 3 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |                        ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
   |
   = note: expected type `&{integer}`
              found type `(_, _)`

error[E0593]: closure takes 1 argument but 2 arguments are required
  --> $DIR/closure-arg-count.rs:3:15
   |
 3 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |               ^^^^^^^ -------------------------- takes 1 argument
   |               |
   |               expected closure that takes 2 arguments


error: aborting due to 2 previous errors

@leonardo-m
Copy link

It's it too much to tell me five times what's the problem? Telling me once or twice should suffice.

@estebank
Copy link
Contributor Author

estebank commented Apr 26, 2017

@leonardo-m I think there might have been a misunderstanding. I believe you were pointing out the output for this error over time, since 1.0 to current nightly, where there were 3 different, but equally unspecific, outputs, as well as suggesting a possible new output. I was pointing out what the new output with this code would be like. Your proposal to point out at only the tuple arg of the closure is not trivial at the moment because I only have the full closure's span to point at, but could be done with some more work. Apologies if you felt I was talking down to you in any way.

So the error messages are essentially the same. And I think they could use an improvement (the first improvement is to generate only one error message).

This PR does that (as pointed out in a prior comment), other than removing the mismatched types error, which I'll try to remove in a clean way in a follow up PR.

@sophiajt
Copy link
Contributor

@leonardo-m - yeah sorry, I wasn't clear either. I think you're pointing out a way it can be improved even further. Can you file an issue with your example so we don't forget and can improve your example also?

I was just trying to make sure we weren't making your example worse with this PR, but it looks like we just have more work to do after this PR.

@leonardo-m
Copy link

Thank you for the work.

Can you file an issue with your example so we don't forget and can improve your example also?

I think it's better to wait for this PR to be merged and inside one Nightly, then I'll take a look at the error message it gives and we can open a new enhancement request.

@estebank
Copy link
Contributor Author

Ping @arielb1, @jonathandturner already 👍'd, I think the only thing left is to make a decision on wether we can leave the last commit's deduplication logic as is until I submit a cleaner follow up PR for that part or we land this PR without that code.

@arielb1
Copy link
Contributor

arielb1 commented May 1, 2017

@estebank

The last commit's deduplication is a hack. I am working on a more principled version but this week is an holiday.

@estebank
Copy link
Contributor Author

estebank commented May 2, 2017

@arielb1 removed the hacky commit.

@arielb1
Copy link
Contributor

arielb1 commented May 2, 2017

@bors r+

@bors
Copy link
Contributor

bors commented May 2, 2017

📌 Commit b10e293 has been approved by arielb1

@bors
Copy link
Contributor

bors commented May 2, 2017

⌛ Testing commit b10e293 with merge 50517d5...

bors added a commit that referenced this pull request May 2, 2017
Clean up callable type mismatch errors

```rust
error[E0593]: closure takes 1 argument but 2 arguments are required here
  --> ../../src/test/ui/mismatched_types/closure-arg-count.rs:13:15
   |
13 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |               ^^^^^^^ -------------------------- takes 1 argument
   |               |
   |               expected closure that takes 2 arguments
```

instead of

```rust
error[E0281]: type mismatch: the type `[closure@../../src/test/ui/mismatched_types/closure-arg-count.rs:13:23: 13:49]` implements the trait `for<'r> std::ops::FnMut<(&'r {integer},)>`, but the trait `for<'r, 'r> std::ops::FnMut<(&'r {integer}, &'r {integer})>` is required (expected a tuple with 2 elements, found one with 1 elements)
  --> ../../src/test/ui/mismatched_types/closure-arg-count.rs:13:15
   |
13 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
   |               ^^^^^^^
```

Fix #21857, re #24680.
@bors
Copy link
Contributor

bors commented May 2, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: arielb1
Pushing 50517d5 to master...

@bors bors merged commit b10e293 into rust-lang:master May 2, 2017
@estebank estebank deleted the closure-args branch November 9, 2023 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants