-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
suggest ?
when method is missing on Result<T, _>
but found on T
#96271
Conversation
r? @nagisa (rust-highfive has picked a reviewer for you, use r? to override) |
Thanks! ❤️
This is an mistake I see newbies make all the time (e.g. in the rust discord) and often this is their first time they encounter Result. IMO it would be better if this error (also) said something along the lines of "this is a result, you need to handle it". |
if let Some(ret_ty) = self | ||
.ret_coercion | ||
.as_ref() | ||
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) | ||
&& let ty::Adt(kind, _) = ret_ty.kind() | ||
&& tcx.get_diagnostic_item(sym::Result) == Some(kind.did()) |
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 checking that the return type is something that ?
can coerce to, right? If the return type isn't that, maybe we can 1) suggest changing the return type and 2) use .unwrap()
. If we do 2), then we should also support this for Option
. We can also build some scaffolding to suggest using if let
, which could work for any ADTs...
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.
Hmmm... I'm not sure if I want to encourage people to .unwrap, though I don't know if we have precedent for that in other suggestions. Or at least, maybe I'll suggest expect.
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.
If we can do the more involved if let
suggestion, that'd be fine by me to skip the unwrap
.
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.
If we can do the more involved
if let
suggestion
Are you suggesting we transform something like:
result.call();
into
if let Ok(value) = result {
value.call();
}
Because if so, I'd probably want to reserve that for a follow-up PR. I need to think of heuristics for when it's meaningful to do so, because I wouldn't want to suggest it for any nested expression, but only ones that are reasonably statement-like on their own. Like not suggesting it when the bad method call is here:
let closure = || call_something(result_needs_unwrap.call(), other_expression());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
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.
Yes, and point taken. As follow up work what we could so is check if the current ty is an enum, and prove each variant that has a single value for the type and emit a note saying "the variant Result::Ok(Ty)
has method foo
" (but still special case for Result
and Option
).
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, I've been thinking of this a bit more, and I would also like to generalize some sort of message to more enums somehow in a follow-up PR.
Let me special-case it for Result
and Option
in this PR, along with suggesting .expect
(and/or changing the return type of the function) when we don't return Result
.
r? @estebank |
@rustbot author |
☔ The latest upstream changes (presumably #96428) made this pull request unmergeable. Please resolve the merge conflicts. |
47328e7
to
d28a216
Compare
|
||
fn test_result_in_plain() { | ||
let res: Result<_, ()> = Ok(Foo); | ||
res.expect("REASON").get(); |
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 just fixup to .unwrap
? I kinda prefer .expect
just because it feels like better practice out of the two.
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 know what you mean, expect is better style, but unwrap ends up looking cleaner... I can be convinced either way.
@rustbot ready |
This comment has been minimized.
This comment has been minimized.
d28a216
to
9db9177
Compare
☔ The latest upstream changes (presumably #96459) made this pull request unmergeable. Please resolve the merge conflicts. |
9db9177
to
90d522e
Compare
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.
Need to continue reviewing, but so far this is a work of art ❤️
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.
LGTM, but left some nitpicks.
@@ -0,0 +1,42 @@ | |||
// run-rustfix |
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.
Let's add a check for async fn
as well. I'm intrigued if they work without further changes.
☔ The latest upstream changes (presumably #97239) made this pull request unmergeable. Please resolve the merge conflicts. |
90d522e
to
a5ec87b
Compare
@rustbot ready |
a5ec87b
to
2a61f0c
Compare
); | ||
} | ||
} | ||
// FIXME(compiler-errors): Support suggestions for other matching enum variants |
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 would entail looking for methods equivalent to .expect
based on heuristics, right?
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.
Maybe, or something like suggesting if let Pattern(destructure) = value { .. }
. Not sure how useful that is, though.
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'd be worth it
@bors r+ |
📌 Commit 2a61f0c has been approved by |
…rk, r=estebank suggest `?` when method is missing on `Result<T, _>` but found on `T` The wording needs help, I think. Fixes rust-lang#95729
…askrgr Rollup of 4 pull requests Successful merges: - rust-lang#96271 (suggest `?` when method is missing on `Result<T, _>` but found on `T`) - rust-lang#97264 (Suggest `extern crate foo` when failing to resolve `use foo`) - rust-lang#97592 (rustdoc: also index impl trait and raw pointers) - rust-lang#97621 (update Miri) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
The wording needs help, I think.
Fixes #95729