-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Improve suggestions for closure parameters #97262
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
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @compiler-errors (or someone else) soon. Please see the contribution instructions for more information. |
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.
There is still the old logic which only works for |x: _|
. This code is still called in that case and I didn't really know how to unify them without potentially breaking other things (though I didn't try that hard). I'm a huge github noob so idk how to comment on that line... it's line 737 in compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs in the new version, 707 on the old version
for arg in fn_sig.inputs().skip_binder().iter() { | ||
if let ControlFlow::Break((ty, _)) = visitor.visit_ty(*arg) { | ||
let mut inner = self.inner.borrow_mut(); | ||
let ty_vars = &inner.type_variables(); |
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.
Can you inline this variable?
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 cannot due to the lifetime of the borrow_mut
:
error[E0716]: temporary value dropped while borrowed
--> compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs:626:42
|
626 | ... let ty_vars= self.inner.borrow_mut().type_variables();
| ^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
...
629 | ... let var_origin = ty_vars.var_origin(ty_vid);
| -------------------------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
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.
sorry, I mean inlining ty_vars
-- like let var_origin = self.inner.borrow_mut().type_variables().var_origin(ty_vid)
?
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.
Thanks for the PR, @kuecks.
There is still the old logic which only works for
|x: _|
.
Do you mean |_|
? Otherwise I'm not sure what you're talking about. Anywho, it's fine to keep this separate from that I think.
Do you mind unifying all of your UI tests into one file? This adds quite a few of the same "kind" of check, so I think it's fine to group them.
}; | ||
err.span_label( | ||
ty_span, | ||
"consider giving this closure parameter an explicit type without `_` placeholders", |
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 prefer a more direct phrasing:
"consider giving this closure parameter an explicit type without `_` placeholders", | |
"give this closure parameter an explicit type instead of `_`", |
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 think it reads a little oddly when the type is something like Vec<_>
since the way you have it written, it sounds like we think the entire closure parameter currently has the type _
(and i copied the wording from the pre-existing return value case). But I don't have super strong feelings either way
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.
makes sense, then can you at least s/consider giving/give
?
); | ||
// We don't want to give the other suggestions when the problem is a | ||
// closure input type. | ||
err.span_label( |
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.
Do you think we need to point out the span of the closure? I kinda like the rendered suggestion of unspecified-parameter.rs
, do you know why it renders differently?
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.
Yeah it renders differently because that's the old code path. I'll see if I can change it so they are uniform, I assume it won't be that hard
I suppose yes? Both of these forms: I actually can't merge the tests because we only emit diagnostics for one at a time. It prefers the
|
That's weird, lol. So some errors are being emitted at a different stage than the others. Alright, well you should at least be able to unify the new cases you added into one file, right? |
No, even the new ones, it only emits one of them (the first one) :( |
let mut visitor = UnresolvedTypeFinder::new(self); | ||
for arg in fn_sig.inputs().skip_binder().iter() { | ||
if let ControlFlow::Break((ty, _)) = visitor.visit_ty(*arg) { |
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.
Can you use InferCtxt::unresolved_type_vars
instead of invoking UnresolvedTypeFinder
yourself?
Also, you probably don't need to use type_variables()
at all -- you can probably just take the Option<Span>
that's returned from unresolved_type_vars
and do .unwrap_or(ty_span)
.
The UnresolvedTypeFinder
already tries to look up the var_origin
of the ty_vid
in question, so you're doing a bit of duplicated work below.
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.
r=me after this
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.
So for some reason, the span is always None when I do this (which is afaict basically the same as what I already have, note that I am currently ignoring the span). I can convert to this and then when it's None
fallback to the current implementation?
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.
Presumably there needs to be another case here? https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_infer/infer/resolve.rs.html#139 I think that would probably be a separate PR but lmk if you want me to take a stab at it
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.
Oh, no actually you should do this:
1.) Edit the UnresolvedTypeFinder
implementation of TypeVisitor
to return the span
always, but also get it to return the TypeVariableOriginKind
(the logic is here) too. The BreakTy
should then be Ty, Span, TypeVariableOriginKind
.
2.) Then edit the existing logic that uses UnresolvedTypeFinder
to now be conditional (I think it's just used in generator_interior.rs
) on that TypeVariableOriginKind
being of type TypeVariableOriginKind::TypeParameterDefinition
.
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.
Edit: actually, the signature will be (Ty, Option<Span>, TypeVariableOriginKind)
. We still probably need to unwrap_or
on the span to deal with when it's None
, but I think you should fall back to the outer span of the closure. You shouldn't need to inspect infcx.inner
in your logic.
eb5ed67
to
7dab378
Compare
7dab378
to
16273eb
Compare
Obsoleted by #97302 |
Currently, the type inference for closures does not handle
_
in the arguments very well. It works specifically for the case of having something like|x: _|
, but not if the_
has any indirection like|x: &_|
or|x: Vec<_>|
etc. Instead, the compiler assumes the issue has to do with the return type annotation, leading to some silly suggestions. The motivating example was this:Which currently gives a silly suggestion:
(playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cb2ba62db3f94f09c2f5dc83217e877e).
This diff changes the diagnostic so that it now looks for any unresolved input parameters before and suggest specifying those before defaulting to the return value.
r? @compiler-errors