Skip to content

Commit a00025a

Browse files
committed
Auto merge of rust-lang#5638 - ebroto:issue_5628_add_suggestion_for_reversed_empty_ranges, r=phansch
reversed_empty_ranges: add suggestion for &slice[N..N] As discussed in the issue thread, the user accepted this solution. Let me know if this is what we want, or if changing the way we lint the N..N case is prefered. changelog: reversed_empty_ranges: add suggestion for &slice[N..N] Closes rust-lang#5628
2 parents 578692d + 60d38ee commit a00025a

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)