rust-lang / rust-lang/rust-clippy
clippy::question_mark lint suggests code that does not compile
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
As part of upgrading pantsbuild to Rust v1.58.0, we had to disable the clippy::question_mark lint on one segment of code because it suggested code that (a) is semantically different and (b) does not actually compile.
Lint Name
clippy::question_mark
Reproducer
Code at issue: https://github.com/pantsbuild/pants/blob/6759bd7ef7b792f26391e70b6b40556020365e81/src/rust/engine/async_value/src/lib.rs#L102-L105
Clippy error:
error: this block may be rewritten with the `?` operator
--> async_value/src/lib.rs:102:7
|
102 | / if item_receiver.changed().await.is_err() {
103 | | return None;
104 | | }
| |_______^ help: replace it with: `item_receiver.changed().await.as_ref()?;`
|
note: the lint level is defined here
--> async_value/src/lib.rs:7:3
|
7 | clippy::all,
| ^^^^^^^^^^^
= note: `#[deny(clippy::question_mark)]` implied by `#[deny(clippy::all)]`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
Applied this diff:
diff --git a/src/rust/engine/async_value/src/lib.rs b/src/rust/engine/async_value/src/lib.rs
index 1133bdf0d..3fb168839 100644
--- a/src/rust/engine/async_value/src/lib.rs
+++ b/src/rust/engine/async_value/src/lib.rs
@@ -99,10 +99,7 @@ impl<T: Clone + Send + Sync + 'static> AsyncValueReceiver<T> {
return Some(value.clone());
}
- #[allow(clippy::question_mark)]
- if item_receiver.changed().await.is_err() {
- return None;
- }
+ item_receiver.changed().await.as_ref()?;
}
}
}
Following clippy's suggestion results in this error:
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in an async function that returns `Option`
--> async_value/src/lib.rs:102:45
|
95 | pub async fn recv(&self) -> Option<T> {
| _________________________________________-
96 | | let mut item_receiver = (*self.item_receiver).clone();
97 | | loop {
98 | | if let Some(ref value) = *item_receiver.borrow() {
... |
102 | | item_receiver.changed().await.as_ref()?;
| | ^ use `.ok()?` if you want to discard the `std::result::Result<std::convert::Infallible, &tokio::sync::watch::error::RecvError>` error information
103 | | }
104 | | }
| |___- this function returns an `Option`
|
= help: the trait `std::ops::FromResidual<std::result::Result<std::convert::Infallible, &tokio::sync::watch::error::RecvError>>` is not implemented for `std::option::Option<T>`
Version
rustc 1.58.0 (02072b482 2022-01-11)
binary: rustc
commit-hash: 02072b482a8b5357f7fb5e5637444ae30e423c40
commit-date: 2022-01-11
host: x86_64-apple-darwin
release: 1.58.0
LLVM version: 13.0.0
Additional Labels
No response
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
Reproduce the clippy::question_mark diagnostic with Rust 1.58.0 using the example in src/rust/engine/async_value/src/lib.rs, then inspect how this lint handles an async function returning Option while the expression returns a Result. Done means the lint no longer suggests code that fails to compile or changes the behavior, with a regression test covering the reported case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100