Skip to content

Commit 356768b

Browse files
committed
Auto merge of rust-lang#11029 - Centri3:empty_slice, r=Jarcho
Make `comparison_to_empty` work on `if let`/`let` chains This adds `LetChain` to `clippy_utils::higher`, other lints may benefit from such a change as well :D changelog: Enhancement: [`comparison_to_empty`]: Now lints on `if let`
2 parents e8403a8 + ae5d391 commit 356768b

File tree

4 files changed

+84
-10
lines changed

4 files changed

+84
-10
lines changed

clippy_lints/src/len_zero.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ use rustc_ast::ast::LitKind;
77
use rustc_errors::Applicability;
88
use rustc_hir::def::Res;
99
use rustc_hir::def_id::{DefId, DefIdSet};
10-
use rustc_hir::lang_items::LangItem;
1110
use rustc_hir::{
1211
AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
13-
ImplicitSelfKind, Item, ItemKind, Mutability, Node, PathSegment, PrimTy, QPath, TraitItemRef, TyKind,
14-
TypeBindingKind,
12+
ImplicitSelfKind, Item, ItemKind, LangItem, Mutability, Node, PatKind, PathSegment, PrimTy, QPath, TraitItemRef,
13+
TyKind, TypeBindingKind,
1514
};
1615
use rustc_lint::{LateContext, LateLintPass};
1716
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -168,6 +167,31 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
168167
return;
169168
}
170169

170+
if let ExprKind::Let(lt) = expr.kind
171+
&& has_is_empty(cx, lt.init)
172+
&& match lt.pat.kind {
173+
PatKind::Slice([], None, []) => true,
174+
PatKind::Lit(lit) if is_empty_string(lit) => true,
175+
_ => false,
176+
}
177+
{
178+
let mut applicability = Applicability::MachineApplicable;
179+
180+
let lit1 = peel_ref_operators(cx, lt.init);
181+
let lit_str =
182+
Sugg::hir_with_context(cx, lit1, lt.span.ctxt(), "_", &mut applicability).maybe_par();
183+
184+
span_lint_and_sugg(
185+
cx,
186+
COMPARISON_TO_EMPTY,
187+
lt.span,
188+
"comparison to empty slice using `if let`",
189+
"using `is_empty` is clearer and more explicit",
190+
format!("{lit_str}.is_empty()"),
191+
applicability,
192+
);
193+
}
194+
171195
if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind {
172196
// expr.span might contains parenthesis, see issue #10529
173197
let actual_span = left.span.with_hi(right.span.hi());

tests/ui/comparison_to_empty.fixed

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//@run-rustfix
22

33
#![warn(clippy::comparison_to_empty)]
4-
#![allow(clippy::useless_vec)]
4+
#![allow(clippy::borrow_deref_ref, clippy::needless_if, clippy::useless_vec)]
5+
#![feature(let_chains)]
56

67
fn main() {
78
// Disallow comparisons to empty
@@ -12,6 +13,11 @@ fn main() {
1213
let v = vec![0];
1314
let _ = v.is_empty();
1415
let _ = !v.is_empty();
16+
if (*v).is_empty() {}
17+
let s = [0].as_slice();
18+
if s.is_empty() {}
19+
if s.is_empty() {}
20+
if s.is_empty() && s.is_empty() {}
1521

1622
// Allow comparisons to non-empty
1723
let s = String::new();
@@ -21,4 +27,8 @@ fn main() {
2127
let v = vec![0];
2228
let _ = v == [0];
2329
let _ = v != [0];
30+
if let [0] = &*v {}
31+
let s = [0].as_slice();
32+
if let [0] = s {}
33+
if let [0] = &*s && s == [0] {}
2434
}

tests/ui/comparison_to_empty.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//@run-rustfix
22

33
#![warn(clippy::comparison_to_empty)]
4-
#![allow(clippy::useless_vec)]
4+
#![allow(clippy::borrow_deref_ref, clippy::needless_if, clippy::useless_vec)]
5+
#![feature(let_chains)]
56

67
fn main() {
78
// Disallow comparisons to empty
@@ -12,6 +13,11 @@ fn main() {
1213
let v = vec![0];
1314
let _ = v == [];
1415
let _ = v != [];
16+
if let [] = &*v {}
17+
let s = [0].as_slice();
18+
if let [] = s {}
19+
if let [] = &*s {}
20+
if let [] = &*s && s == [] {}
1521

1622
// Allow comparisons to non-empty
1723
let s = String::new();
@@ -21,4 +27,8 @@ fn main() {
2127
let v = vec![0];
2228
let _ = v == [0];
2329
let _ = v != [0];
30+
if let [0] = &*v {}
31+
let s = [0].as_slice();
32+
if let [0] = s {}
33+
if let [0] = &*s && s == [0] {}
2434
}

tests/ui/comparison_to_empty.stderr

+35-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,58 @@
11
error: comparison to empty slice
2-
--> $DIR/comparison_to_empty.rs:9:13
2+
--> $DIR/comparison_to_empty.rs:10:13
33
|
44
LL | let _ = s == "";
55
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
66
|
77
= note: `-D clippy::comparison-to-empty` implied by `-D warnings`
88

99
error: comparison to empty slice
10-
--> $DIR/comparison_to_empty.rs:10:13
10+
--> $DIR/comparison_to_empty.rs:11:13
1111
|
1212
LL | let _ = s != "";
1313
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
1414

1515
error: comparison to empty slice
16-
--> $DIR/comparison_to_empty.rs:13:13
16+
--> $DIR/comparison_to_empty.rs:14:13
1717
|
1818
LL | let _ = v == [];
1919
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
2020

2121
error: comparison to empty slice
22-
--> $DIR/comparison_to_empty.rs:14:13
22+
--> $DIR/comparison_to_empty.rs:15:13
2323
|
2424
LL | let _ = v != [];
2525
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
2626

27-
error: aborting due to 4 previous errors
27+
error: comparison to empty slice using `if let`
28+
--> $DIR/comparison_to_empty.rs:16:8
29+
|
30+
LL | if let [] = &*v {}
31+
| ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(*v).is_empty()`
32+
33+
error: comparison to empty slice using `if let`
34+
--> $DIR/comparison_to_empty.rs:18:8
35+
|
36+
LL | if let [] = s {}
37+
| ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
38+
39+
error: comparison to empty slice using `if let`
40+
--> $DIR/comparison_to_empty.rs:19:8
41+
|
42+
LL | if let [] = &*s {}
43+
| ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
44+
45+
error: comparison to empty slice using `if let`
46+
--> $DIR/comparison_to_empty.rs:20:8
47+
|
48+
LL | if let [] = &*s && s == [] {}
49+
| ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
50+
51+
error: comparison to empty slice
52+
--> $DIR/comparison_to_empty.rs:20:24
53+
|
54+
LL | if let [] = &*s && s == [] {}
55+
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
56+
57+
error: aborting due to 9 previous errors
2858

0 commit comments

Comments
 (0)