rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.46k stars 1.54k forks source link

[Pattern_type_mismatch] clippy encouraging to dereference, but not needed. #12325

Open t-webber opened 8 months ago

t-webber commented 8 months ago

Summary

When I match an Option<String>, and when ownership is not required, I often reference the data using a &. However, dereferencing with & doesn't give the right type (&Option<String> instead of Option<&String>), so with [(clippy::pattern_type_mismatch)], I get a warning. Thus I use as_ref(), and that is what I feal clippy should tell me to do. Instead, the clippy warning tells me to dereference the expression, but by doing so, the ownership is gone for the lines after the end of the match expression.

Reproducer

I tried this code:

#[warn(clippy::pattern_type_mismatch)]
fn main() {
    let wrapped_data: Option<String> = Some("Hello".to_owned());
    if let Some(data) = &wrapped_data {
        println!("Access to data: {}", &data);
    };
    println!("Data still owned: {wrapped_data:?}");
}

Clippy suggests:

use * to dereference the match expression or explicitly match against a &_ pattern and adjust the enclosed variable bindings

However, if dereferenced, wrapped_data looses ownership and the last line will fail.

Clippy should suggest:

use _.as_ref() to reference on the content of an Option instead of &_.

Version

rustc 1.78.0-nightly (a4472498d 2024-02-15)
binary: rustc
commit-hash: a4472498d7e88041f6206faf4503eb1f246fd427
commit-date: 2024-02-15
host: x86_64-pc-windows-msvc
release: 1.78.0-nightly
LLVM version: 18.1.0

Additional Labels

No response

### Tasks
TomFryersMidsummer commented 2 months ago

The second suggestion it gives is the one that works here. It's telling you to do this:

#[warn(clippy::pattern_type_mismatch)]
fn main() {
    let wrapped_data: Option<String> = Some("Hello".to_owned());
    if let &Some(ref data) = &wrapped_data {
        println!("Access to data: {}", &data);
    };
    println!("Data still owned: {wrapped_data:?}");
}