Skip to content

len_without_is_empty triggers when both len and is_empty have non-standard signatures #9520

@lopopolo

Description

@lopopolo

Summary

I have a proxy type (a symbol from a string interner) which has len and is_empty method which:

  • are fallible
  • take the interner as a method parameter

len_without_is_empty triggers with these methods, which is unexpected since neither method matches the method signature the lint looks for.

Lint Name

len_without_is_empty

Reproducer

I tried this code:

#[warn(clippy::len_without_is_empty)]

pub trait Intern {
    type Symbol: Copy;
    
    fn lookup_symbol(&self, sym: Self::Symbol) -> Result<Option<&[u8]>, String>;
}


#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Symbol(u32);

impl Symbol {
    #[inline]
    #[must_use]
    pub fn is_empty<T, U>(self, interner: &T) -> bool
    where
        T: Intern<Symbol = U>,
        U: Copy + From<Symbol>,
    {
        if let Ok(Some(bytes)) = interner.lookup_symbol(self.into()) {
            bytes.is_empty()
        } else {
            true
        }
    }

    #[inline]
    #[must_use]
    // #[allow(clippy::len_without_is_empty)]
    pub fn len<T, U>(self, interner: &T) -> usize
    where
        T: Intern<Symbol = U>,
        U: Copy + From<Symbol>,
    {
        if let Ok(Some(bytes)) = interner.lookup_symbol(self.into()) {
            bytes.len()
        } else {
            0_usize
        }
    }
}

I saw this happen:

    Checking playground v0.0.1 (/playground)
warning: struct `Symbol` has a public `len` method, but the `is_empty` method has an unexpected signature
  --> src/lib.rs:31:5
   |
31 | /     pub fn len<T, U>(self, interner: &T) -> usize
32 | |     where
33 | |         T: Intern<Symbol = U>,
34 | |         U: Copy + From<Symbol>,
   | |_______________________________^
   |
   = note: `#[warn(clippy::len_without_is_empty)]` on by default
note: `is_empty` defined here
  --> src/lib.rs:16:5
   |
16 | /     pub fn is_empty<T, U>(self, interner: &T) -> bool
17 | |     where
18 | |         T: Intern<Symbol = U>,
19 | |         U: Copy + From<Symbol>,
   | |_______________________________^
   = note: expected signature: `(self) -> bool`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty

warning: `playground` (lib) generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.48s

I expected to see this happen: No error because neither len nor is_empty has the expected signature.

Version

rustc 1.64.0 (a55dd71d5 2022-09-19)
binary: rustc
commit-hash: a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52
commit-date: 2022-09-19
host: x86_64-apple-darwin
release: 1.64.0
LLVM version: 14.0.6

Additional Labels

No response

Metadata

Metadata

Assignees

Labels

C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't havegood first issueThese issues are a good way to get started with Clippy

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions