From 2fd94a4e01d9e8049df3651d0b29b3964cf235d8 Mon Sep 17 00:00:00 2001 From: ksaleem Date: Sun, 29 Jan 2023 13:48:06 -0500 Subject: [PATCH] prevents `len_without_is_empty` from yielding positive when `len` takes more than just `&self` in non-standard implementations. changelog: Fix [`len_without_is_empty`] false positive when len has a non-standard method signature Fixes #9520 --- clippy_lints/src/len_zero.rs | 1 + tests/ui/len_without_is_empty.rs | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 3c70c9cf19a..920ab7f0633 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -135,6 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); + if sig.decl.inputs.len() == 1; if cx.effective_visibilities.is_exported(item.owner_id.def_id); if matches!(sig.decl.output, FnRetTy::Return(_)); if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs index 78397c2af34..b5dec6c46bd 100644 --- a/tests/ui/len_without_is_empty.rs +++ b/tests/ui/len_without_is_empty.rs @@ -282,4 +282,50 @@ impl AsyncLen { } } +// issue #9520 +pub struct NonStandardLenAndIsEmptySignature; +impl NonStandardLenAndIsEmptySignature { + // don't lint + pub fn len(&self, something: usize) -> usize { + something + } + + pub fn is_empty(&self, something: usize) -> bool { + something == 0 + } +} + +// test case for #9520 with generics in the function signature +pub trait TestResource { + type NonStandardSignatureWithGenerics: Copy; + fn lookup_content(&self, item: Self::NonStandardSignatureWithGenerics) -> Result, String>; +} +pub struct NonStandardSignatureWithGenerics(u32); +impl NonStandardSignatureWithGenerics { + pub fn is_empty(self, resource: &T) -> bool + where + T: TestResource, + U: Copy + From, + { + if let Ok(Some(content)) = resource.lookup_content(self.into()) { + content.is_empty() + } else { + true + } + } + + // test case for #9520 with generics in the function signature + pub fn len(self, resource: &T) -> usize + where + T: TestResource, + U: Copy + From, + { + if let Ok(Some(content)) = resource.lookup_content(self.into()) { + content.len() + } else { + 0_usize + } + } +} + fn main() {}