-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Summary
If you're match
ing on some reference type (e.g. &Option<String>
) and in the Some
case are passing the produced inner reference (e.g. &String
) to a function taking a reference, then the result from following clippy:option_if_let_else
's suggestion will not compile.
Reproducer
I tried this code:
#![warn(clippy::option_if_let_else)]
pub fn reproduce(initial: &Option<String>) {
match initial {
Some(value) => do_something(value),
None => {}
}
}
fn do_something(_value: &str) {}
Clippy produces the following warning:
❯ cargo clippy
warning: use Option::map_or instead of an if let/else
--> src/lib.rs:4:5
|
4 | / match initial {
5 | | Some(value) => do_something(value),
6 | | None => {}
7 | | }
| |_____^ help: try: `initial.map_or({}, |value| do_something(value))`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else
note: the lint level is defined here
--> src/lib.rs:1:9
|
1 | #![warn(clippy::option_if_let_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `clippy-bug-repro` (lib) generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Following the suggestion results in this code:
#![warn(clippy::option_if_let_else)]
pub fn reproduce(initial: &Option<String>) {
initial.map_or({}, |value| do_something(value))
}
fn do_something(_value: &str) {}
Which fails to compile with:
❯ cargo build
Compiling clippy-bug-repro v0.1.0 (/home/yami/dev/repos/clippy-bug-repro)
error[E0308]: mismatched types
--> src/lib.rs:4:45
|
4 | initial.map_or({}, |value| do_something(value))
| ------------ ^^^^^
| | |
| | expected `&str`, found `String`
| | help: consider borrowing here: `&value`
| arguments to this function are incorrect
|
note: function defined here
--> src/lib.rs:7:4
|
7 | fn do_something(_value: &str) {}
| ^^^^^^^^^^^^ ------------
For more information about this error, try `rustc --explain E0308`.
error: could not compile `clippy-bug-repro` (lib) due to previous error
Further "whack-a-mole" results that may not be considered directly relevant to this issue, but are probably still useful as a reference.
Following that suggestion also does not compile:
❯ cargo build
Compiling clippy-bug-repro v0.1.0 (/home/yami/dev/repos/clippy-bug-repro)
error[E0507]: cannot move out of `*initial` which is behind a shared reference
--> src/lib.rs:4:5
|
4 | initial.map_or({}, |value| do_something(&value))
| ^^^^^^^^----------------------------------------
| | |
| | `*initial` moved due to this method call
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*initial` has type `Option<String>`, which does not implement the `Copy` trait
|
note: `Option::<T>::map_or` takes ownership of the receiver `self`, which moves `*initial`
--> /home/yami/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1155:31
|
1155 | pub const fn map_or<U, F>(self, default: U, f: F) -> U
| ^^^^
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
4 | initial.clone().map_or({}, |value| do_something(&value))
| ++++++++
For more information about this error, try `rustc --explain E0507`.
error: could not compile `clippy-bug-repro` (lib) due to previous error
Following the suggestion to change initial.map_or(...)
to initial.as_ref().map_or(...)
starts to compile, but results in two more warnings:
❯ cargo clippy
warning: passing a unit value to a function
--> src/lib.rs:4:5
|
4 | initial.as_ref().map_or({}, |value| do_something(&value))
| ^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| help: use a unit literal instead: `()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
= note: `#[warn(clippy::unit_arg)]` on by default
warning: this expression creates a reference which is immediately dereferenced by the compiler
--> src/lib.rs:4:54
|
4 | initial.as_ref().map_or({}, |value| do_something(&value))
| ^^^^^^ help: change this to: `value`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
= note: `#[warn(clippy::needless_borrow)]` on by default
warning: `clippy-bug-repro` (lib) generated 2 warnings (run `cargo clippy --fix --lib -p clippy-bug-repro` to apply 2 suggestions)
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
The clippy::unit_arg
is fair, and I imagine is purely an artefact of my reproduction's None
branch being a no-op.
However, the suggestion for clippy::needless_borrow
actually undoes the original (incorrect) suggestion made in the context of clippy::option_if_let_else
. I imagine this would need to be considered when "fixing" this issue.
Version
rustc 1.70.0-beta.2 (071f14baa 2023-04-30)
binary: rustc
commit-hash: 071f14baae931e17a5a99366bf216e76384cc4f6
commit-date: 2023-04-30
host: x86_64-unknown-linux-gnu
release: 1.70.0-beta.2
LLVM version: 16.0.2
Additional Labels
@rustbot label +I-suggestion-causes-error