-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Fix wrong report on closure args mismatch when a ref is expected but not found #42270
Conversation
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. |
I would personally prefer to issue the error message when you find that the obligation & closure trait refs are function traits whose first arguments are tuples of different arg-counts, rather than trying to match against type errors. |
I think this is the same thing that @arielb1 was saying, but I feel like we could do a lot better with this error message. That is, ideally, we would tell the user that the closure is declared with argument type I think the error message we want is probably something like this:
|
@@ -684,24 +684,36 @@ 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 { | |||
let expected_len = if let ty::TyTuple(tys, _) = expected_found.expected.sty { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh. I am a bit dubious about this if
in the first-place. I guess I have to run the code -- what happens if you just remove this logic altogether, though? It feels very odd to me to have to do all this matching.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(In other words, the logic here feels quite suspect, even before your changes.)
I agree with what has been commented here. I'll get to the implementation most likely tomorrow. Should I open a new pr for it or just force push a new commit? |
Force push is probably fine in this case since changes are small; in general just a normal push would be best |
@Emilgardis force push is good -- thanks! |
Hi @Emilgardis! Just a friendly ping to keep this on your radar :) |
@Emilgardis do you think you know how to do the better error message, or do you want a few tips? |
Sorry for the delay, I have a unpushed commit on my local branch, I've also implemented E0604, and I'm now trying to get a correct output of the types that where mismatched. i.e show |
I realised that the error:
Is awfully closely related to E0281, should I remove my local E0604 and just change E0281 to give prettier output and have it be called on code like the example above instead of E0604? 281 is currently
|
Do you need any help @Emilgardis? Feel free to ask me on IRC (I'm arielb1 or arielby). |
@Emilgardis it's always a tough call where to use a distinct error number. I think in this case it is worth keeping a distinct error number, though. Basically this is because we can give a more specialized --explain description targeting the particular case of closure arguments. Also, there is a sort of distinction here: the more general mismatched types refers to the value itself, whereas this is saying that the types in the trait that the closure implements don't match. (Also, the current infrastructure makes it difficult to combine error messages in any case.) |
@Emilgardis sounds like you have something working? I guess you didn't yet push those commits? The preview looks very appealing though! |
@Emilgardis I couldn't find you on IRC. Are you still interested in working on this? Should I get this done myself? |
Sorry for not being active, I'll get to this tomorrow (in 7-10 hours). I'm Emilgardis on mozilla |
Hi @Emilgardis, did you get a chance to come back to this? |
Yes, I have a working branch on temp-issue-42143. I'll get to rebasing it onto changes upstream today regarding a new error code |
@Emilgardis awesome :) |
when a ref is expected but not found. Adds new error E0622 Fixes rust-lang#42143
There we go. Should be all fine. I'll address some concerns I have in a review. |
--> $DIR/closure-arg-type-mismatch.rs:16:27 | ||
| | ||
16 | let d1 = a.iter().map(|x: &(u16,u16)| 45); | ||
| ^^^ ------------------ takes a `for<'r> std::ops::FnMut<(&'r (u16, u16),)>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this binder/lifetime be displayed?
15 | let b = a.iter().map(|x: (u32, u32)| 45); | ||
| ^^^ ------------------ takes a `std::ops::FnMut<((u32, u32),)>` | ||
| | | ||
| expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about implementing a hint telling the user to add a &
/&mut
to the closure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I couldn't find a way (except for "parsing") to convert Fn*<([&]({T} ... ))>
(meaning what is displayed here as FnMut<(&(u32, u32),)>
) into a simple &(u32, u32)
as @nikomatsakis suggested.
f2b7256
to
a41f93f
Compare
New error code is E0623 Also cleanup/fix ui test
I'm not sure how to proceed. E0281 is very similar to E0623. Infact, what I can see the two errors are almost always the same. |
let mut err = struct_span_err!(self.tcx.sess, span, E0623, | ||
"type mismatch in closure arguments"); | ||
if let Some(sp) = found_span { | ||
err.span_label(span, format!("expected closure that takes a `{}`", found)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should be able to extract the types of the arguments by examining the substs of the expected_ref
and found
trait-refs. Something like:
let expected_args = expected_ref.map_bound_ref(|trait_ref| trait_ref.substs.type_at(1));
But it might need to be type_at(0)
. That will give you a Binder<Ty<'tcx>>
, which you should be able to use with {}
I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good! Last step is just to extract the types, and not print the whole trait, left some comments, let me know how it goes (feel free to reach out on IRC etc)
@Emilgardis ping? |
@Emilgardis ping. I'll be on vacation for the rest of the week, but if you need any help you can talk with @nikomatsakis . |
Closing due to inactivity. Feel free to reopen when you can find me. |
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: `[[email protected]: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
Fixes #42143.
Also adds test for this case.