Auto merge of #6980 - Jarcho:len_without_is_empty_sig, r=llogiq

`len_without_is_empty` improvements

fixes: #6958
fixes: #6972

changelog: Check the return type of `len`. Only integral types, or an `Option` or `Result` wrapping one.
changelog: Ensure the return type of `is_empty` matches. e.g. `Option<usize>` -> `Option<bool>`
This commit is contained in:
bors 2021-03-27 13:10:43 +00:00
commit dcee00d64b
3 changed files with 231 additions and 25 deletions

View file

@ -1,3 +1,5 @@
// edition:2018
#![warn(clippy::len_without_is_empty)]
#![allow(dead_code, unused)]
@ -172,9 +174,9 @@ pub trait DependsOnFoo: Foo {
fn len(&mut self) -> usize;
}
// issue #1562
pub struct MultipleImpls;
// issue #1562
impl MultipleImpls {
pub fn len(&self) -> usize {
1
@ -187,4 +189,99 @@ impl MultipleImpls {
}
}
// issue #6958
pub struct OptionalLen;
impl OptionalLen {
pub fn len(&self) -> Option<usize> {
Some(0)
}
pub fn is_empty(&self) -> Option<bool> {
Some(true)
}
}
pub struct OptionalLen2;
impl OptionalLen2 {
pub fn len(&self) -> Option<usize> {
Some(0)
}
pub fn is_empty(&self) -> bool {
true
}
}
pub struct OptionalLen3;
impl OptionalLen3 {
pub fn len(&self) -> usize {
0
}
// should lint, len is not an option
pub fn is_empty(&self) -> Option<bool> {
None
}
}
pub struct ResultLen;
impl ResultLen {
pub fn len(&self) -> Result<usize, ()> {
Ok(0)
}
// Differing result types
pub fn is_empty(&self) -> Option<bool> {
Some(true)
}
}
pub struct ResultLen2;
impl ResultLen2 {
pub fn len(&self) -> Result<usize, ()> {
Ok(0)
}
pub fn is_empty(&self) -> Result<bool, ()> {
Ok(true)
}
}
pub struct ResultLen3;
impl ResultLen3 {
pub fn len(&self) -> Result<usize, ()> {
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 {
if self.async_task().await { 0 } else { 1 }
}
pub async fn is_empty(&self) -> bool {
self.len().await == 0
}
}
fn main() {}

View file

@ -1,5 +1,5 @@
error: struct `PubOne` has a public `len` method, but no `is_empty` method
--> $DIR/len_without_is_empty.rs:7:5
--> $DIR/len_without_is_empty.rs:9:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,7 +7,7 @@ LL | pub fn len(&self) -> isize {
= note: `-D clippy::len-without-is-empty` implied by `-D warnings`
error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
--> $DIR/len_without_is_empty.rs:55:1
--> $DIR/len_without_is_empty.rs:57:1
|
LL | / pub trait PubTraitsToo {
LL | | fn len(&self) -> isize;
@ -15,50 +15,109 @@ LL | | }
| |_^
error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method
--> $DIR/len_without_is_empty.rs:68:5
--> $DIR/len_without_is_empty.rs:70:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
--> $DIR/len_without_is_empty.rs:72:5
--> $DIR/len_without_is_empty.rs:74:5
|
LL | fn is_empty(&self) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature
--> $DIR/len_without_is_empty.rs:80:5
--> $DIR/len_without_is_empty.rs:82:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
--> $DIR/len_without_is_empty.rs:84:5
--> $DIR/len_without_is_empty.rs:86:5
|
LL | pub fn is_empty(&self, x: u32) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool`
error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature
--> $DIR/len_without_is_empty.rs:92:5
--> $DIR/len_without_is_empty.rs:94:5
|
LL | pub fn len(self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
--> $DIR/len_without_is_empty.rs:96:5
--> $DIR/len_without_is_empty.rs:98:5
|
LL | pub fn is_empty(&self) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(self) -> bool`
error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
--> $DIR/len_without_is_empty.rs:171:1
--> $DIR/len_without_is_empty.rs:173:1
|
LL | / pub trait DependsOnFoo: Foo {
LL | | fn len(&mut self) -> usize;
LL | | }
| |_^
error: aborting due to 6 previous errors
error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature
--> $DIR/len_without_is_empty.rs:218:5
|
LL | pub fn len(&self) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
--> $DIR/len_without_is_empty.rs:223:5
|
LL | pub fn is_empty(&self) -> Option<bool> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool`
error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature
--> $DIR/len_without_is_empty.rs:230:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
--> $DIR/len_without_is_empty.rs:235:5
|
LL | pub fn is_empty(&self) -> Option<bool> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool>
error: this returns a `Result<_, ()>
--> $DIR/len_without_is_empty.rs:230:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::result-unit-err` implied by `-D warnings`
= help: use a custom Error type instead
error: this returns a `Result<_, ()>
--> $DIR/len_without_is_empty.rs:242:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a custom Error type instead
error: this returns a `Result<_, ()>
--> $DIR/len_without_is_empty.rs:246:5
|
LL | pub fn is_empty(&self) -> Result<bool, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a custom Error type instead
error: this returns a `Result<_, ()>
--> $DIR/len_without_is_empty.rs:253:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a custom Error type instead
error: aborting due to 12 previous errors