Skip to content

Commit 60d38ee

Browse files
committed
reversed_empty_ranges: add suggestion for &slice[N..N]
1 parent c41916d commit 60d38ee

6 files changed

+47
-24
lines changed

clippy_lints/src/ranges.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,14 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
241241
}
242242

243243
fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
244-
fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
245-
matches!(
246-
get_parent_expr(cx, expr),
247-
Some(Expr {
244+
fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> Option<&'a Expr<'a>> {
245+
match get_parent_expr(cx, expr) {
246+
parent_expr @ Some(Expr {
248247
kind: ExprKind::Index(..),
249248
..
250-
})
251-
)
249+
}) => parent_expr,
250+
_ => None,
251+
}
252252
}
253253

254254
fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
@@ -267,18 +267,32 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
267267
if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
268268
if is_empty_range(limits, ordering);
269269
then {
270-
if inside_indexing_expr(cx, expr) {
270+
if let Some(parent_expr) = inside_indexing_expr(cx, expr) {
271271
let (reason, outcome) = if ordering == Ordering::Equal {
272272
("empty", "always yield an empty slice")
273273
} else {
274274
("reversed", "panic at run-time")
275275
};
276276

277-
span_lint(
277+
span_lint_and_then(
278278
cx,
279279
REVERSED_EMPTY_RANGES,
280280
expr.span,
281281
&format!("this range is {} and using it to index a slice will {}", reason, outcome),
282+
|diag| {
283+
if_chain! {
284+
if ordering == Ordering::Equal;
285+
if let ty::Slice(slice_ty) = cx.tables.expr_ty(parent_expr).kind;
286+
then {
287+
diag.span_suggestion(
288+
parent_expr.span,
289+
"if you want an empty slice, use",
290+
format!("[] as &[{}]", slice_ty),
291+
Applicability::MaybeIncorrect
292+
);
293+
}
294+
}
295+
}
282296
);
283297
} else {
284298
span_lint_and_then(

tests/ui/reversed_empty_ranges_fixable.fixed

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
const ANSWER: i32 = 42;
55

66
fn main() {
7+
let arr = [1, 2, 3, 4, 5];
8+
9+
// These should be linted:
10+
711
(21..=42).rev().for_each(|x| println!("{}", x));
812
let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
913

1014
for _ in (-42..=-21).rev() {}
1115
for _ in (21u32..42u32).rev() {}
1216

17+
let _ = &[] as &[i32];
18+
1319
// These should be ignored as they are not empty ranges:
1420

1521
(21..=42).for_each(|x| println!("{}", x));
1622
(21..42).for_each(|x| println!("{}", x));
1723

18-
let arr = [1, 2, 3, 4, 5];
1924
let _ = &arr[1..=3];
2025
let _ = &arr[1..3];
2126

tests/ui/reversed_empty_ranges_fixable.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
const ANSWER: i32 = 42;
55

66
fn main() {
7+
let arr = [1, 2, 3, 4, 5];
8+
9+
// These should be linted:
10+
711
(42..=21).for_each(|x| println!("{}", x));
812
let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
913

1014
for _ in -21..=-42 {}
1115
for _ in 42u32..21u32 {}
1216

17+
let _ = &arr[3..3];
18+
1319
// These should be ignored as they are not empty ranges:
1420

1521
(21..=42).for_each(|x| println!("{}", x));
1622
(21..42).for_each(|x| println!("{}", x));
1723

18-
let arr = [1, 2, 3, 4, 5];
1924
let _ = &arr[1..=3];
2025
let _ = &arr[1..3];
2126

tests/ui/reversed_empty_ranges_fixable.stderr

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this range is empty so it will yield no values
2-
--> $DIR/reversed_empty_ranges_fixable.rs:7:5
2+
--> $DIR/reversed_empty_ranges_fixable.rs:11:5
33
|
44
LL | (42..=21).for_each(|x| println!("{}", x));
55
| ^^^^^^^^^
@@ -11,7 +11,7 @@ LL | (21..=42).rev().for_each(|x| println!("{}", x));
1111
| ^^^^^^^^^^^^^^^
1212

1313
error: this range is empty so it will yield no values
14-
--> $DIR/reversed_empty_ranges_fixable.rs:8:13
14+
--> $DIR/reversed_empty_ranges_fixable.rs:12:13
1515
|
1616
LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
1717
| ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Ve
2222
| ^^^^^^^^^^^^^^^^^^
2323

2424
error: this range is empty so it will yield no values
25-
--> $DIR/reversed_empty_ranges_fixable.rs:10:14
25+
--> $DIR/reversed_empty_ranges_fixable.rs:14:14
2626
|
2727
LL | for _ in -21..=-42 {}
2828
| ^^^^^^^^^
@@ -33,7 +33,7 @@ LL | for _ in (-42..=-21).rev() {}
3333
| ^^^^^^^^^^^^^^^^^
3434

3535
error: this range is empty so it will yield no values
36-
--> $DIR/reversed_empty_ranges_fixable.rs:11:14
36+
--> $DIR/reversed_empty_ranges_fixable.rs:15:14
3737
|
3838
LL | for _ in 42u32..21u32 {}
3939
| ^^^^^^^^^^^^
@@ -43,5 +43,11 @@ help: consider using the following if you are attempting to iterate over this ra
4343
LL | for _ in (21u32..42u32).rev() {}
4444
| ^^^^^^^^^^^^^^^^^^^^
4545

46-
error: aborting due to 4 previous errors
46+
error: this range is empty and using it to index a slice will always yield an empty slice
47+
--> $DIR/reversed_empty_ranges_fixable.rs:17:18
48+
|
49+
LL | let _ = &arr[3..3];
50+
| ----^^^^- help: if you want an empty slice, use: `[] as &[i32]`
51+
52+
error: aborting due to 5 previous errors
4753

tests/ui/reversed_empty_ranges_unfixable.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ fn main() {
99
let arr = [1, 2, 3, 4, 5];
1010
let _ = &arr[3usize..=1usize];
1111
let _ = &arr[SOME_NUM..1];
12-
let _ = &arr[3..3];
1312

1413
for _ in ANSWER..ANSWER {}
1514
}

tests/ui/reversed_empty_ranges_unfixable.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,11 @@ error: this range is reversed and using it to index a slice will panic at run-ti
1818
LL | let _ = &arr[SOME_NUM..1];
1919
| ^^^^^^^^^^^
2020

21-
error: this range is empty and using it to index a slice will always yield an empty slice
22-
--> $DIR/reversed_empty_ranges_unfixable.rs:12:18
23-
|
24-
LL | let _ = &arr[3..3];
25-
| ^^^^
26-
2721
error: this range is empty so it will yield no values
28-
--> $DIR/reversed_empty_ranges_unfixable.rs:14:14
22+
--> $DIR/reversed_empty_ranges_unfixable.rs:13:14
2923
|
3024
LL | for _ in ANSWER..ANSWER {}
3125
| ^^^^^^^^^^^^^^
3226

33-
error: aborting due to 5 previous errors
27+
error: aborting due to 4 previous errors
3428

0 commit comments

Comments
 (0)