#![warn(clippy::len_without_is_empty)] #![allow(dead_code, unused)] pub struct PubOne; impl PubOne { pub fn len(&self) -> isize { //~^ ERROR: struct `PubOne` has a public `len` method, but no `is_empty` method //~| NOTE: `-D clippy::len-without-is-empty` implied by `-D warnings` 1 } } impl PubOne { // A second impl for this struct -- the error span shouldn't mention this. pub fn irrelevant(&self) -> bool { false } } // Identical to `PubOne`, but with an `allow` attribute on the impl complaining `len`. pub struct PubAllowed; #[allow(clippy::len_without_is_empty)] impl PubAllowed { pub fn len(&self) -> isize { 1 } } // No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the // impl containing `len`. impl PubAllowed { pub fn irrelevant(&self) -> bool { false } } pub struct PubAllowedFn; impl PubAllowedFn { #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> isize { 1 } } #[allow(clippy::len_without_is_empty)] pub struct PubAllowedStruct; impl PubAllowedStruct { pub fn len(&self) -> isize { 1 } } pub trait PubTraitsToo { //~^ ERROR: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` fn len(&self) -> isize; } impl PubTraitsToo for One { fn len(&self) -> isize { 0 } } pub struct HasIsEmpty; impl HasIsEmpty { pub fn len(&self) -> isize { //~^ ERROR: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` me 1 } fn is_empty(&self) -> bool { false } } pub struct HasWrongIsEmpty; impl HasWrongIsEmpty { pub fn len(&self) -> isize { //~^ ERROR: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` met 1 } pub fn is_empty(&self, x: u32) -> bool { false } } pub struct MismatchedSelf; impl MismatchedSelf { pub fn len(self) -> isize { //~^ ERROR: struct `MismatchedSelf` has a public `len` method, but the `is_empty` meth 1 } pub fn is_empty(&self) -> bool { false } } struct NotPubOne; impl NotPubOne { pub fn len(&self) -> isize { // No error; `len` is pub but `NotPubOne` is not exported anyway. 1 } } struct One; impl One { fn len(&self) -> isize { // No error; `len` is private; see issue #1085. 1 } } trait TraitsToo { fn len(&self) -> isize; // No error; `len` is private; see issue #1085. } impl TraitsToo for One { fn len(&self) -> isize { 0 } } struct HasPrivateIsEmpty; impl HasPrivateIsEmpty { pub fn len(&self) -> isize { 1 } fn is_empty(&self) -> bool { false } } struct Wither; pub trait WithIsEmpty { fn len(&self) -> isize; fn is_empty(&self) -> bool; } impl WithIsEmpty for Wither { fn len(&self) -> isize { 1 } fn is_empty(&self) -> bool { false } } pub trait Empty { fn is_empty(&self) -> bool; } pub trait InheritingEmpty: Empty { // Must not trigger `LEN_WITHOUT_IS_EMPTY`. fn len(&self) -> isize; } // This used to ICE. pub trait Foo: Sized {} pub trait DependsOnFoo: Foo { //~^ ERROR: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` fn len(&mut self) -> usize; } // issue #1562 pub struct MultipleImpls; impl MultipleImpls { pub fn len(&self) -> usize { 1 } } impl MultipleImpls { pub fn is_empty(&self) -> bool { false } } // issue #6958 pub struct OptionalLen; impl OptionalLen { pub fn len(&self) -> Option { Some(0) } pub fn is_empty(&self) -> Option { Some(true) } } pub struct OptionalLen2; impl OptionalLen2 { pub fn len(&self) -> Option { Some(0) } pub fn is_empty(&self) -> bool { true } } pub struct OptionalLen3; impl OptionalLen3 { pub fn len(&self) -> usize { //~^ ERROR: struct `OptionalLen3` has a public `len` method, but the `is_empty` method 0 } // should lint, len is not an option pub fn is_empty(&self) -> Option { None } } pub struct ResultLen; impl ResultLen { pub fn len(&self) -> Result { //~^ ERROR: struct `ResultLen` has a public `len` method, but the `is_empty` method ha //~| ERROR: this returns a `Result<_, ()>` Ok(0) } // Differing result types pub fn is_empty(&self) -> Option { Some(true) } } pub struct ResultLen2; impl ResultLen2 { pub fn len(&self) -> Result { //~^ ERROR: this returns a `Result<_, ()>` Ok(0) } pub fn is_empty(&self) -> Result { //~^ ERROR: this returns a `Result<_, ()>` Ok(true) } } pub struct ResultLen3; impl ResultLen3 { pub fn len(&self) -> Result { //~^ ERROR: this returns a `Result<_, ()>` Ok(0) } // Non-fallible result is ok. pub fn is_empty(&self) -> bool { true } } pub struct OddLenSig; impl OddLenSig { // don't lint pub fn len(&self) -> bool { true } } // issue #6958 pub struct AsyncLen; impl AsyncLen { async fn async_task(&self) -> bool { true } pub async fn len(&self) -> usize { usize::from(!self.async_task().await) } pub async fn is_empty(&self) -> bool { self.len().await == 0 } } // issue #7232 pub struct AsyncLenWithoutIsEmpty; impl AsyncLenWithoutIsEmpty { pub async fn async_task(&self) -> bool { true } pub async fn len(&self) -> usize { //~^ ERROR: struct `AsyncLenWithoutIsEmpty` has a public `len` method, but no `is_empt usize::from(!self.async_task().await) } } // issue #7232 pub struct AsyncOptionLenWithoutIsEmpty; impl AsyncOptionLenWithoutIsEmpty { async fn async_task(&self) -> bool { true } pub async fn len(&self) -> Option { //~^ ERROR: struct `AsyncOptionLenWithoutIsEmpty` has a public `len` method, but no `i None } } // issue #7232 pub struct AsyncOptionLenNonIntegral; impl AsyncOptionLenNonIntegral { // don't lint pub async fn len(&self) -> Option { None } } // issue #7232 pub struct AsyncResultLenWithoutIsEmpty; impl AsyncResultLenWithoutIsEmpty { async fn async_task(&self) -> bool { true } pub async fn len(&self) -> Result { //~^ ERROR: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no `i Err(()) } } // issue #7232 pub struct AsyncOptionLen; impl AsyncOptionLen { async fn async_task(&self) -> bool { true } pub async fn len(&self) -> Result { Err(()) } pub async fn is_empty(&self) -> bool { true } } pub struct AsyncLenSyncIsEmpty; impl AsyncLenSyncIsEmpty { pub async fn len(&self) -> u32 { 0 } pub fn is_empty(&self) -> bool { true } } // issue #9520 pub struct NonStandardLen; impl NonStandardLen { // don't lint pub fn len(&self, something: usize) -> usize { something } } // 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 } } } pub struct DifferingErrors; impl DifferingErrors { pub fn len(&self) -> Result { Ok(0) } pub fn is_empty(&self) -> Result { Ok(true) } } fn main() {}