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

suggest ? when method is missing on Result<T, _> but found on T #96271

Merged
merged 2 commits into from
Jun 1, 2022

Conversation

compiler-errors
Copy link
Member

The wording needs help, I think.

Fixes #95729

@rust-highfive
Copy link
Collaborator

r? @nagisa

(rust-highfive has picked a reviewer for you, use r? to override)

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 21, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 21, 2022
@mejrs
Copy link
Contributor

mejrs commented Apr 21, 2022

Thanks! ❤️

The wording needs help, I think.

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".

Comment on lines 1146 to 1151
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())
Copy link
Contributor

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...

Copy link
Member Author

@compiler-errors compiler-errors Apr 23, 2022

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.

Copy link
Contributor

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.

Copy link
Member Author

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());
//                              ^^^^^^^^^^^^^^^^^^^^^^^^^^

Copy link
Contributor

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).

Copy link
Member Author

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.

@nagisa
Copy link
Member

nagisa commented Apr 24, 2022

r? @estebank

@rust-highfive rust-highfive assigned estebank and unassigned nagisa Apr 24, 2022
@compiler-errors
Copy link
Member Author

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 25, 2022
@bors
Copy link
Contributor

bors commented Apr 26, 2022

☔ The latest upstream changes (presumably #96428) made this pull request unmergeable. Please resolve the merge conflicts.


fn test_result_in_plain() {
let res: Result<_, ()> = Ok(Foo);
res.expect("REASON").get();
Copy link
Member Author

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.

Copy link
Contributor

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.

@compiler-errors
Copy link
Member Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 27, 2022
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Apr 27, 2022

☔ The latest upstream changes (presumably #96459) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Contributor

@estebank estebank left a 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 ❤️

Copy link
Contributor

@estebank estebank left a 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.

compiler/rustc_typeck/src/check/method/suggest.rs Outdated Show resolved Hide resolved
compiler/rustc_typeck/src/check/method/suggest.rs Outdated Show resolved Hide resolved
compiler/rustc_typeck/src/check/method/suggest.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,42 @@
// run-rustfix
Copy link
Contributor

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.

@bors
Copy link
Contributor

bors commented May 21, 2022

☔ The latest upstream changes (presumably #97239) made this pull request unmergeable. Please resolve the merge conflicts.

@compiler-errors
Copy link
Member Author

@rustbot ready

);
}
}
// FIXME(compiler-errors): Support suggestions for other matching enum variants
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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

@estebank
Copy link
Contributor

estebank commented Jun 1, 2022

@bors r+

@bors
Copy link
Contributor

bors commented Jun 1, 2022

📌 Commit 2a61f0c has been approved by estebank

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 1, 2022
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jun 1, 2022
…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
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 1, 2022
…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
@bors bors merged commit 7d4cf71 into rust-lang:master Jun 1, 2022
@rustbot rustbot added this to the 1.63.0 milestone Jun 1, 2022
@compiler-errors compiler-errors deleted the suggest-question-mark branch August 11, 2023 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unhelpful error when forgetting to handle a result and call a method on it
8 participants