Skip to content

needless_borrowed_reference makes invalid suggestions #13035

Open
@wr7

Description

@wr7

Summary

&ref in a match arm can perform dereferencing, and clippy::needless_borrowed_reference does not seem to take this into consideration.

Lint Name

clippy::needless_borrowed_reference

Reproducer

I tried this code:

pub enum HasData<'a> {
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}

pub fn foo(val: &HasData) {
    match val {
        HasData::V(&ref data) => expects_box(data.into()),
    }
}

cargo clippy --fix output:

The following errors were reported:
error[E0277]: the trait bound `std::boxed::Box<[u8]>: std::convert::From<&&[u8]>` is not satisfied
 --> src/lib.rs:9:46
  |
9 |         HasData::V(data) => expects_box(data.into()),
  |                                              ^^^^ the trait `std::convert::From<&&[u8]>` is not implemented for `std::boxed::Box<[u8]>`, which is required by `&&[u8]: std::convert::Into<_>`
  |
  = help: the following other types implement trait `std::convert::From<T>`:
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<&str>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<E>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<std::borrow::Cow<'b, str>>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<std::string::String>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<&str>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<E>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<std::borrow::Cow<'b, str>>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<std::string::String>>
          and 18 others
  = note: required for `&&[u8]` to implement `std::convert::Into<std::boxed::Box<[u8]>>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original diagnostics will follow.

warning: this pattern takes a reference on something that is being dereferenced
 --> src/lib.rs:9:20
  |
9 |         HasData::V(&ref data) => expects_box(data.into()),
  |                    ^^^^^^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
  = note: `#[warn(clippy::needless_borrowed_reference)]` on by default
help: try removing the `&ref` part
  |
9 -         HasData::V(&ref data) => expects_box(data.into()),
9 +         HasData::V(data) => expects_box(data.into()),
  |

warning: `rust-test` (lib test) generated 1 warning (run `cargo clippy --fix --lib -p rust-test --tests` to apply 1 suggestion)
warning: failed to automatically apply fixes suggested by rustc to crate `rust_test`

after fixes were automatically applied the compiler reported errors within these files:

  * src/lib.rs

This likely indicates a bug in either rustc or cargo itself,
and we would appreciate a bug report! You're likely to see
a number of compiler warnings after this message which cargo
attempted to fix but failed. If you could open an issue at
https://github.com/rust-lang/rust-clippy/issues
quoting the full output of this command we'd be very appreciative!
Note that you may be able to make some more progress in the near-term
fixing code with the `--broken-code` flag

The following errors were reported:
error[E0277]: the trait bound `std::boxed::Box<[u8]>: std::convert::From<&&[u8]>` is not satisfied
 --> src/lib.rs:9:46
  |
9 |         HasData::V(data) => expects_box(data.into()),
  |                                              ^^^^ the trait `std::convert::From<&&[u8]>` is not implemented for `std::boxed::Box<[u8]>`, which is required by `&&[u8]: std::convert::Into<_>`
  |
  = help: the following other types implement trait `std::convert::From<T>`:
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<&str>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<E>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<std::borrow::Cow<'b, str>>>
            <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<std::string::String>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<&str>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<E>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<std::borrow::Cow<'b, str>>>
            <std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'a)> as std::convert::From<std::string::String>>
          and 18 others
  = note: required for `&&[u8]` to implement `std::convert::Into<std::boxed::Box<[u8]>>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.

Expected behavior

Add a deref to val and then remove the &ref

pub enum HasData<'a> {
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}

pub fn foo(val: &HasData) {
    match *val {
        HasData::V(data) => expects_box(data.into()),
    }
}

More complex cases

More complex cases should not be corrected or the following corrections should be applied.

Other match variables

ref should be added to other matched variables.

The following example

pub enum HasData<'a> {
    U(String),
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}
fn expects_str(_: &str) {}

pub fn foo(val: &HasData) {
    match val {
        HasData::U(string) => expects_str(string),
        HasData::V(&ref data) => expects_box(data.into()),
    }
}

should be corrected to:

pub enum HasData<'a> {
    U(String),
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}
fn expects_str(_: &str) {}

pub fn foo(val: &HasData) {
    match *val {
        HasData::U(ref string) => expects_str(string),
        HasData::V(data) => expects_box(data.into()),
    }
}

Multiple references

The matched value should be dereferenced until it is bare.

The following example

pub enum HasData<'a> {
    U(String),
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}
fn expects_str(_: &str) {}

pub fn foo(val: &&HasData) {
    match val {
        HasData::U(string) => expects_str(string),
        HasData::V(&ref data) => expects_box(data.into()),
    }
}

should be corrected to:

pub enum HasData<'a> {
    U(String),
    V(&'a [u8]),
}

fn expects_box(_: Box<[u8]>) {}
fn expects_str(_: &str) {}

pub fn foo(val: &&HasData) {
    match **val {
        HasData::U(ref string) => expects_str(string),
        HasData::V(data) => expects_box(data.into()),
    }
}

Version

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7

Additional Labels

@rustbot label +I-suggestion-causes-error
@rustbot label -I-false-positive

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions