rust-clippy icon indicating copy to clipboard operation
rust-clippy copied to clipboard

needless_borrow false positive in case when compiler does not automatically borrow

Open leighmcculloch opened this issue 3 years ago • 8 comments

Summary

The needless_borrow lint has a false positive where the suggested fix results in code that won't compile, because the compiler doesn't automatically borrow, even though the lint says it does.

Lint Name

needless_borrow

Reproducer

I tried this code:

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct VecM<T, const MAX: u32 = { u32::MAX }>(Vec<T>);

impl<T: Clone, const N: usize, const MAX: u32> TryFrom<&[T; N]> for VecM<T, MAX> {
    type Error = ();

    fn try_from(v: &[T; N]) -> Result<Self, ()> {
        todo!()
    }
}

#[cfg(test)]
mod test {
    use crate::VecM;

    #[test]
    fn test_try_from() {
        let _vm: VecM<u8, 32> = (&[]).try_into().unwrap();
        //let _vm: VecM<u8, 32> = [].try_into().unwrap();
    }
}
❯ cargo clippy --all-targets
    Checking clippy-needless-borrow v0.1.0 (/Users/leighmcculloch/Code/clippy-needless-borrow)
warning: this expression borrows a value the compiler would automatically borrow
  --> src/lib.rs:23:33
   |
18 |         let _vm: VecM<u8, 32> = (&[]).try_into().unwrap();
   |                                 ^^^^^ help: change this to: `[]`
   |
   = note: `#[warn(clippy::needless_borrow)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

warning: `clippy-needless-borrow` (lib test) generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s

Making the change that clippy suggests, results in the following and the following compiler error:

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct VecM<T, const MAX: u32 = { u32::MAX }>(Vec<T>);

impl<T: Clone, const N: usize, const MAX: u32> TryFrom<&[T; N]> for VecM<T, MAX> {
    type Error = ();

    fn try_from(v: &[T; N]) -> Result<Self, ()> {
        todo!()
    }
}

#[cfg(test)]
mod test {
    use crate::VecM;

    #[test]
    fn test_try_from() {
        //let _vm: VecM<u8, 32> = (&[]).try_into().unwrap();
        let _vm: VecM<u8, 32> = [].try_into().unwrap();
    }
}
❯ cargo clippy --all-targets
    Checking clippy-needless-borrow v0.1.0 (/Users/leighmcculloch/Code/clippy-needless-borrow)
error[E0277]: the trait bound `VecM<u8, 32_u32>: std::convert::From<[_; 0]>` is not satisfied
  --> src/lib.rs:24:36
   |
19 |         let _vm: VecM<u8, 32> = [].try_into().unwrap();
   |                                    ^^^^^^^^ the trait `std::convert::From<[_; 0]>` is not implemented for `VecM<u8, 32_u32>`
   |
   = note: required because of the requirements on the impl of `std::convert::Into<VecM<u8, 32_u32>>` for `[_; 0]`
   = note: required because of the requirements on the impl of `std::convert::TryFrom<[_; 0]>` for `VecM<u8, 32_u32>`
   = note: required because of the requirements on the impl of `std::convert::TryInto<VecM<u8, 32_u32>>` for `[_; 0]`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `clippy-needless-borrow` due to previous error

Version

❯ rustc -Vv
rustc 1.64.0-nightly (f2d93935f 2022-07-02)
binary: rustc
commit-hash: f2d93935ffba3ab9d7ccb5300771a2d29b4c8bf3
commit-date: 2022-07-02
host: x86_64-apple-darwin
release: 1.64.0-nightly
LLVM version: 14.0.6

Additional Labels

@rustbot label +I-suggestion-causes-error

leighmcculloch avatar Jul 03 '22 15:07 leighmcculloch

Looks to be the same as #9095. Checking if a generic trait is implemented by a reference type isn't working correctly.

Jarcho avatar Jul 03 '22 18:07 Jarcho

Looks to be the same as #9095. Checking if a generic trait is implemented by a reference type isn't working correctly.

https://github.com/rust-lang/rust-clippy/issues/9095 is fixed, but I still have this issue in 2022-07-17.

droogmic avatar Jul 17 '22 21:07 droogmic

The fix hasn't been merged into the main rustc repo yet.

Jarcho avatar Jul 17 '22 23:07 Jarcho

ah true, I thought I had seen a release go out.

droogmic avatar Jul 18 '22 16:07 droogmic

Has this been released? I am still seeing this with rustup 2022-09-08 toolchain.

yshui avatar Sep 09 '22 09:09 yshui

The issue is fixed on the 2022-09-16 toolchain (tested on playground)

kraktus avatar Sep 17 '22 12:09 kraktus

Do you know in which PR/commit ?

poliorcetics avatar Sep 17 '22 12:09 poliorcetics

I'd assume https://github.com/rust-lang/rust-clippy/pull/9096

kraktus avatar Sep 17 '22 12:09 kraktus

I'm still getting similar false positive on 2022-10-13.

struct A;

impl Extend<u8> for A {
    fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) { unimplemented!() }
}

impl<'a> Extend<&'a u8> for A {
    fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) { unimplemented!() }
}

fn main() {
    let mut a = A;
    a.extend(&[]); // vs a.extend([]);
}

BusyJay avatar Oct 13 '22 06:10 BusyJay

@BusyJay With your example, I see:

warning: the borrowed expression implements the required traits
  --> src/main.rs:13:14
   |
13 |     a.extend(&[]); // vs a.extend([]);
   |              ^^^ help: change this to: `[]`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

I think this is a different bug.

smoelius avatar Oct 13 '22 07:10 smoelius

This issue seems to be fixed. None of the reproducers mentioned here get linted anymore it looks like: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3c4b7032d2e1c46d488b42a1a5cc4627

y21 avatar Jun 16 '23 01:06 y21

Thank you for triaging.

Jarcho avatar Jun 16 '23 01:06 Jarcho