needless_borrow false positive in case when compiler does not automatically borrow
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
Looks to be the same as #9095. Checking if a generic trait is implemented by a reference type isn't working correctly.
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.
The fix hasn't been merged into the main rustc repo yet.
ah true, I thought I had seen a release go out.
Has this been released? I am still seeing this with rustup 2022-09-08 toolchain.
The issue is fixed on the 2022-09-16 toolchain (tested on playground)
Do you know in which PR/commit ?
I'd assume https://github.com/rust-lang/rust-clippy/pull/9096
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 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.
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
Thank you for triaging.