Skip to content

Commit 77fbdb6

Browse files
committed
Auto merge of #3978 - phansch:rustfix_len_zero, r=flip1995
Add run-rustfix for len_zero lint * Extracts len_without_is_empty into separate file * Adds `// run-rustfix` to `tests/ui/len_zero.rs` cc #3630
2 parents c6e43b1 + bae7d29 commit 77fbdb6

File tree

5 files changed

+367
-163
lines changed

5 files changed

+367
-163
lines changed

tests/ui/len_without_is_empty.rs

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#![warn(clippy::len_without_is_empty)]
2+
#![allow(dead_code, unused)]
3+
4+
pub struct PubOne;
5+
6+
impl PubOne {
7+
pub fn len(self: &Self) -> isize {
8+
1
9+
}
10+
}
11+
12+
impl PubOne {
13+
// A second impl for this struct -- the error span shouldn't mention this.
14+
pub fn irrelevant(self: &Self) -> bool {
15+
false
16+
}
17+
}
18+
19+
// Identical to `PubOne`, but with an `allow` attribute on the impl complaining `len`.
20+
pub struct PubAllowed;
21+
22+
#[allow(clippy::len_without_is_empty)]
23+
impl PubAllowed {
24+
pub fn len(self: &Self) -> isize {
25+
1
26+
}
27+
}
28+
29+
// No `allow` attribute on this impl block, but that doesn't matter -- we only require one on the
30+
// impl containing `len`.
31+
impl PubAllowed {
32+
pub fn irrelevant(self: &Self) -> bool {
33+
false
34+
}
35+
}
36+
37+
pub trait PubTraitsToo {
38+
fn len(self: &Self) -> isize;
39+
}
40+
41+
impl PubTraitsToo for One {
42+
fn len(self: &Self) -> isize {
43+
0
44+
}
45+
}
46+
47+
pub struct HasIsEmpty;
48+
49+
impl HasIsEmpty {
50+
pub fn len(self: &Self) -> isize {
51+
1
52+
}
53+
54+
fn is_empty(self: &Self) -> bool {
55+
false
56+
}
57+
}
58+
59+
pub struct HasWrongIsEmpty;
60+
61+
impl HasWrongIsEmpty {
62+
pub fn len(self: &Self) -> isize {
63+
1
64+
}
65+
66+
pub fn is_empty(self: &Self, x: u32) -> bool {
67+
false
68+
}
69+
}
70+
71+
struct NotPubOne;
72+
73+
impl NotPubOne {
74+
pub fn len(self: &Self) -> isize {
75+
// No error; `len` is pub but `NotPubOne` is not exported anyway.
76+
1
77+
}
78+
}
79+
80+
struct One;
81+
82+
impl One {
83+
fn len(self: &Self) -> isize {
84+
// No error; `len` is private; see issue #1085.
85+
1
86+
}
87+
}
88+
89+
trait TraitsToo {
90+
fn len(self: &Self) -> isize;
91+
// No error; `len` is private; see issue #1085.
92+
}
93+
94+
impl TraitsToo for One {
95+
fn len(self: &Self) -> isize {
96+
0
97+
}
98+
}
99+
100+
struct HasPrivateIsEmpty;
101+
102+
impl HasPrivateIsEmpty {
103+
pub fn len(self: &Self) -> isize {
104+
1
105+
}
106+
107+
fn is_empty(self: &Self) -> bool {
108+
false
109+
}
110+
}
111+
112+
struct Wither;
113+
114+
pub trait WithIsEmpty {
115+
fn len(self: &Self) -> isize;
116+
fn is_empty(self: &Self) -> bool;
117+
}
118+
119+
impl WithIsEmpty for Wither {
120+
fn len(self: &Self) -> isize {
121+
1
122+
}
123+
124+
fn is_empty(self: &Self) -> bool {
125+
false
126+
}
127+
}
128+
129+
pub trait Empty {
130+
fn is_empty(&self) -> bool;
131+
}
132+
133+
pub trait InheritingEmpty: Empty {
134+
// Must not trigger `LEN_WITHOUT_IS_EMPTY`.
135+
fn len(&self) -> isize;
136+
}
137+
138+
// This used to ICE.
139+
pub trait Foo: Sized {}
140+
141+
pub trait DependsOnFoo: Foo {
142+
fn len(&mut self) -> usize;
143+
}
144+
145+
fn main() {}

tests/ui/len_without_is_empty.stderr

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error: item `PubOne` has a public `len` method but no corresponding `is_empty` method
2+
--> $DIR/len_without_is_empty.rs:6:1
3+
|
4+
LL | / impl PubOne {
5+
LL | | pub fn len(self: &Self) -> isize {
6+
LL | | 1
7+
LL | | }
8+
LL | | }
9+
| |_^
10+
|
11+
= note: `-D clippy::len-without-is-empty` implied by `-D warnings`
12+
13+
error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
14+
--> $DIR/len_without_is_empty.rs:37:1
15+
|
16+
LL | / pub trait PubTraitsToo {
17+
LL | | fn len(self: &Self) -> isize;
18+
LL | | }
19+
| |_^
20+
21+
error: item `HasIsEmpty` has a public `len` method but a private `is_empty` method
22+
--> $DIR/len_without_is_empty.rs:49:1
23+
|
24+
LL | / impl HasIsEmpty {
25+
LL | | pub fn len(self: &Self) -> isize {
26+
LL | | 1
27+
LL | | }
28+
... |
29+
LL | | }
30+
LL | | }
31+
| |_^
32+
33+
error: item `HasWrongIsEmpty` has a public `len` method but no corresponding `is_empty` method
34+
--> $DIR/len_without_is_empty.rs:61:1
35+
|
36+
LL | / impl HasWrongIsEmpty {
37+
LL | | pub fn len(self: &Self) -> isize {
38+
LL | | 1
39+
LL | | }
40+
... |
41+
LL | | }
42+
LL | | }
43+
| |_^
44+
45+
error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
46+
--> $DIR/len_without_is_empty.rs:141:1
47+
|
48+
LL | / pub trait DependsOnFoo: Foo {
49+
LL | | fn len(&mut self) -> usize;
50+
LL | | }
51+
| |_^
52+
53+
error: aborting due to 5 previous errors
54+

tests/ui/len_zero.fixed

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::len_zero)]
4+
#![allow(dead_code, unused, clippy::len_without_is_empty)]
5+
6+
pub struct One;
7+
struct Wither;
8+
9+
trait TraitsToo {
10+
fn len(self: &Self) -> isize;
11+
// No error; `len` is private; see issue #1085.
12+
}
13+
14+
impl TraitsToo for One {
15+
fn len(self: &Self) -> isize {
16+
0
17+
}
18+
}
19+
20+
pub struct HasIsEmpty;
21+
22+
impl HasIsEmpty {
23+
pub fn len(self: &Self) -> isize {
24+
1
25+
}
26+
27+
fn is_empty(self: &Self) -> bool {
28+
false
29+
}
30+
}
31+
32+
pub struct HasWrongIsEmpty;
33+
34+
impl HasWrongIsEmpty {
35+
pub fn len(self: &Self) -> isize {
36+
1
37+
}
38+
39+
pub fn is_empty(self: &Self, x: u32) -> bool {
40+
false
41+
}
42+
}
43+
44+
pub trait WithIsEmpty {
45+
fn len(self: &Self) -> isize;
46+
fn is_empty(self: &Self) -> bool;
47+
}
48+
49+
impl WithIsEmpty for Wither {
50+
fn len(self: &Self) -> isize {
51+
1
52+
}
53+
54+
fn is_empty(self: &Self) -> bool {
55+
false
56+
}
57+
}
58+
59+
fn main() {
60+
let x = [1, 2];
61+
if x.is_empty() {
62+
println!("This should not happen!");
63+
}
64+
65+
if "".is_empty() {}
66+
67+
let y = One;
68+
if y.len() == 0 {
69+
// No error; `One` does not have `.is_empty()`.
70+
println!("This should not happen either!");
71+
}
72+
73+
let z: &TraitsToo = &y;
74+
if z.len() > 0 {
75+
// No error; `TraitsToo` has no `.is_empty()` method.
76+
println!("Nor should this!");
77+
}
78+
79+
let has_is_empty = HasIsEmpty;
80+
if has_is_empty.is_empty() {
81+
println!("Or this!");
82+
}
83+
if !has_is_empty.is_empty() {
84+
println!("Or this!");
85+
}
86+
if !has_is_empty.is_empty() {
87+
println!("Or this!");
88+
}
89+
if has_is_empty.is_empty() {
90+
println!("Or this!");
91+
}
92+
if !has_is_empty.is_empty() {
93+
println!("Or this!");
94+
}
95+
if has_is_empty.len() > 1 {
96+
// No error.
97+
println!("This can happen.");
98+
}
99+
if has_is_empty.len() <= 1 {
100+
// No error.
101+
println!("This can happen.");
102+
}
103+
if has_is_empty.is_empty() {
104+
println!("Or this!");
105+
}
106+
if !has_is_empty.is_empty() {
107+
println!("Or this!");
108+
}
109+
if !has_is_empty.is_empty() {
110+
println!("Or this!");
111+
}
112+
if !has_is_empty.is_empty() {
113+
println!("Or this!");
114+
}
115+
if has_is_empty.is_empty() {
116+
println!("Or this!");
117+
}
118+
if 1 < has_is_empty.len() {
119+
// No error.
120+
println!("This can happen.");
121+
}
122+
if 1 >= has_is_empty.len() {
123+
// No error.
124+
println!("This can happen.");
125+
}
126+
assert!(!has_is_empty.is_empty());
127+
128+
let with_is_empty: &WithIsEmpty = &Wither;
129+
if with_is_empty.is_empty() {
130+
println!("Or this!");
131+
}
132+
assert!(!with_is_empty.is_empty());
133+
134+
let has_wrong_is_empty = HasWrongIsEmpty;
135+
if has_wrong_is_empty.len() == 0 {
136+
// No error; `HasWrongIsEmpty` does not have `.is_empty()`.
137+
println!("Or this!");
138+
}
139+
}
140+
141+
fn test_slice(b: &[u8]) {
142+
if !b.is_empty() {}
143+
}

0 commit comments

Comments
 (0)