Skip to content

clippy::question_mark lint suggests code that does not compile #8281

Open
@tdyas

Description

@tdyas

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions