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

Unnecessary use of .ok() followed by method equivalently defined on both Option and Result #8994

Open
junbl opened this issue Jun 13, 2022 · 2 comments
Labels
A-lint Area: New lints

Comments

@junbl
Copy link

junbl commented Jun 13, 2022

What it does

There is an existing lint, ok_expect, that warns against the following code:

res.ok().expect("msg")

saying that the .ok() can be removed and expect called directly. This can be generalized to other methods that can be called on both Option and Result.

The methods I could find that this could apply to include:

  • expect
  • unwrap, unwrap_or, unwrap_or_default, unwrap_unchecked
  • iter, iter_mut, into_iter
  • map_or

I'm sure I've missed some, please add any others that could be included!

The lazily evaluated _else methods could also be included with the minor modification of adding a ignored argument to the closure for the error, e.g. res.ok().unwrap_or_else(|| 4) becomes res.unwrap_or_else(|_| 4).

This could also be applied to calls to methods with multiple arguments if .ok() is called on both (e.g. .or(), .and(), .cmp()), though this is likely less common.

The reverse lint could also be implemented, e.g. unnecessary use of ok_or(_else) on an Option followed by a method above that will never construct the Err. The call to ok_or_else could have side effects, however, making the suggested code not equivalent.

Lint Name

unnecessary_ok

Category

complexity, perf

Advantage

  • Removes unnecessary code, improving clarity
  • Removes an unnecessary conversion (I don't know much about compiler internals---this may be a nonexistent performance change)

Drawbacks

Might not be a common enough pattern to be worth it. I've personally seen .ok().map_or.

The unwrap_* methods require that the Err variant implement Debug, which otherwise wouldn't be necessary.

Example

let value = <Result<_, i32>>::Ok(4);
value.ok().unwrap(); // or any of the above methods

Could be written as:

let value = <Result<_, i32>>::Ok(4);
value.unwrap();
@junbl junbl added the A-lint Area: New lints label Jun 13, 2022
@hkBst
Copy link
Contributor

hkBst commented Nov 15, 2022

Another form of unnecessary ok that I found in the wild is as an unidiomatic way to ignore an error:

Example

dotenv().ok();

This could be written more idiomatically as:

let _ = dotenv();

Although one can argue that instead this should have been written:

dotenv().unwrap();

@ithinuel
Copy link
Contributor

@hkBst I have also seen this in several places (embedded oriented here and there) used to ignore the result (because known to be unfallible, or not relevant).

bors added a commit that referenced this issue Aug 6, 2024
Add lint for `unused_result_ok`

This PR adds a lint to capture the use of `expr.ok();` when the result is not _really_ used.

This could be interpreted as the result being checked (like it is with `unwrap()` or `expect`) but
it actually only ignores the result.

`let _ = expr;` expresses that intent better.

This was also mentionned in #8994 (although not being the main topic of that issue).

changelog: [`misleading_use_of_ok`]: Add new lint to capture `.ok();` when the result is not _really_ used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

3 participants