rust-lang / rust-lang/rust-clippy
add a non-default lint to ban question mark operators for Option
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
What it does
(This is a suggestion for a non-default lint.)
With this lint, uses of ? would be banned in any methods that returned Option<T>. Instead, code would be written using the let Some(v) = ... else { return None } pattern.
Advantage
Over time I've become quite disenchanted with the question mark operator for Option<T> -- while it has some uses, in my experience it is one of the most common sources of bugs in code I write.
A recent example of a bug is this commit, where I refactored a Result<Option<T>> into an Option<T>: https://github.com/nextest-rs/nextest/commit/7f68c0e80fb1ee993576f2757ee1b1ddbe75619c. There were some ? in this code whose meaning changed dramatically due to the refactor, and the compiler/clippy didn't point this out at all. I had to fix that later in https://github.com/nextest-rs/nextest/commit/e92436f8b0ffb65addf75a5d50ab196553eaabb3 (partly by completely removing Option).
This is not the first time this has happened, and the presence of ? for Option has started making me wary of using Option in general -- often you don't just want to return None if a child function returned None, unlike errors where you do generally want to do that.
So I would love a lint which lets me ban ? in general, while possibly enabling it for particular blocks where the ? pattern is genuinely useful. The alternative recommended (let Some(v) ... else { ... }) is wordier, but also more robust to semantic changes during refactors.
Drawbacks
The alternative is more verbose.
Example
fn foo() -> Option<T> { ... }
fn bar() -> Option<T> {
let v = foo()?;
...
}
Could be written as:
fn foo() -> Option<T> { ... }
fn bar() -> Option<T> {
let Some(v) = foo() else {
return None;
}
...
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the two linked nextest commits and the issue's Option and Result<Option> examples to understand the proposed semantic problem. Then investigate how Clippy currently represents non-default lints and handles the ? operator. Done means the lint's scope and opt-in behavior are defined well enough for implementation, including how block-level exceptions should work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100