about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduardo Broto <ebroto@tutanota.com>2020-05-23 22:07:03 +0200
committerEduardo Broto <ebroto@tutanota.com>2020-05-25 20:06:15 +0200
commit60d38ee1dde4344daa5fdf716eef78b45f483c7e (patch)
tree214935a8a85e004e69fb35539a6dcbb4b9adfda3
parentc41916d9bd2ca98c9291d07a095503d9e934da60 (diff)
downloadrust-60d38ee1dde4344daa5fdf716eef78b45f483c7e.tar.gz
rust-60d38ee1dde4344daa5fdf716eef78b45f483c7e.zip
reversed_empty_ranges: add suggestion for &slice[N..N]
-rw-r--r--clippy_lints/src/ranges.rs30
-rw-r--r--tests/ui/reversed_empty_ranges_fixable.fixed7
-rw-r--r--tests/ui/reversed_empty_ranges_fixable.rs7
-rw-r--r--tests/ui/reversed_empty_ranges_fixable.stderr16
-rw-r--r--tests/ui/reversed_empty_ranges_unfixable.rs1
-rw-r--r--tests/ui/reversed_empty_ranges_unfixable.stderr10
6 files changed, 47 insertions, 24 deletions
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 83c6faac041..1eb26d97ed4 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -241,14 +241,14 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
 }
 
 fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
-    fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
-        matches!(
-            get_parent_expr(cx, expr),
-            Some(Expr {
+    fn inside_indexing_expr<'a>(cx: &'a LateContext<'_, '_>, expr: &Expr<'_>) -> Option<&'a Expr<'a>> {
+        match get_parent_expr(cx, expr) {
+            parent_expr @ Some(Expr {
                 kind: ExprKind::Index(..),
                 ..
-            })
-        )
+            }) => parent_expr,
+            _ => None,
+        }
     }
 
     fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
@@ -267,18 +267,32 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
         if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
         if is_empty_range(limits, ordering);
         then {
-            if inside_indexing_expr(cx, expr) {
+            if let Some(parent_expr) = inside_indexing_expr(cx, expr) {
                 let (reason, outcome) = if ordering == Ordering::Equal {
                     ("empty", "always yield an empty slice")
                 } else {
                     ("reversed", "panic at run-time")
                 };
 
-                span_lint(
+                span_lint_and_then(
                     cx,
                     REVERSED_EMPTY_RANGES,
                     expr.span,
                     &format!("this range is {} and using it to index a slice will {}", reason, outcome),
+                    |diag| {
+                        if_chain! {
+                            if ordering == Ordering::Equal;
+                            if let ty::Slice(slice_ty) = cx.tables.expr_ty(parent_expr).kind;
+                            then {
+                                diag.span_suggestion(
+                                    parent_expr.span,
+                                    "if you want an empty slice, use",
+                                    format!("[] as &[{}]", slice_ty),
+                                    Applicability::MaybeIncorrect
+                                );
+                            }
+                        }
+                    }
                 );
             } else {
                 span_lint_and_then(
diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed
index ee2cbc3cf54..332c0427ef6 100644
--- a/tests/ui/reversed_empty_ranges_fixable.fixed
+++ b/tests/ui/reversed_empty_ranges_fixable.fixed
@@ -4,18 +4,23 @@
 const ANSWER: i32 = 42;
 
 fn main() {
+    let arr = [1, 2, 3, 4, 5];
+
+    // These should be linted:
+
     (21..=42).rev().for_each(|x| println!("{}", x));
     let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
 
     for _ in (-42..=-21).rev() {}
     for _ in (21u32..42u32).rev() {}
 
+    let _ = &[] as &[i32];
+
     // These should be ignored as they are not empty ranges:
 
     (21..=42).for_each(|x| println!("{}", x));
     (21..42).for_each(|x| println!("{}", x));
 
-    let arr = [1, 2, 3, 4, 5];
     let _ = &arr[1..=3];
     let _ = &arr[1..3];
 
diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs
index 6ed5ca6daa0..901ec8bcc09 100644
--- a/tests/ui/reversed_empty_ranges_fixable.rs
+++ b/tests/ui/reversed_empty_ranges_fixable.rs
@@ -4,18 +4,23 @@
 const ANSWER: i32 = 42;
 
 fn main() {
+    let arr = [1, 2, 3, 4, 5];
+
+    // These should be linted:
+
     (42..=21).for_each(|x| println!("{}", x));
     let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
 
     for _ in -21..=-42 {}
     for _ in 42u32..21u32 {}
 
+    let _ = &arr[3..3];
+
     // These should be ignored as they are not empty ranges:
 
     (21..=42).for_each(|x| println!("{}", x));
     (21..42).for_each(|x| println!("{}", x));
 
-    let arr = [1, 2, 3, 4, 5];
     let _ = &arr[1..=3];
     let _ = &arr[1..3];
 
diff --git a/tests/ui/reversed_empty_ranges_fixable.stderr b/tests/ui/reversed_empty_ranges_fixable.stderr
index 97933b8ff85..9a646fd9939 100644
--- a/tests/ui/reversed_empty_ranges_fixable.stderr
+++ b/tests/ui/reversed_empty_ranges_fixable.stderr
@@ -1,5 +1,5 @@
 error: this range is empty so it will yield no values
-  --> $DIR/reversed_empty_ranges_fixable.rs:7:5
+  --> $DIR/reversed_empty_ranges_fixable.rs:11:5
    |
 LL |     (42..=21).for_each(|x| println!("{}", x));
    |     ^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     (21..=42).rev().for_each(|x| println!("{}", x));
    |     ^^^^^^^^^^^^^^^
 
 error: this range is empty so it will yield no values
-  --> $DIR/reversed_empty_ranges_fixable.rs:8:13
+  --> $DIR/reversed_empty_ranges_fixable.rs:12:13
    |
 LL |     let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Ve
    |             ^^^^^^^^^^^^^^^^^^
 
 error: this range is empty so it will yield no values
-  --> $DIR/reversed_empty_ranges_fixable.rs:10:14
+  --> $DIR/reversed_empty_ranges_fixable.rs:14:14
    |
 LL |     for _ in -21..=-42 {}
    |              ^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     for _ in (-42..=-21).rev() {}
    |              ^^^^^^^^^^^^^^^^^
 
 error: this range is empty so it will yield no values
-  --> $DIR/reversed_empty_ranges_fixable.rs:11:14
+  --> $DIR/reversed_empty_ranges_fixable.rs:15:14
    |
 LL |     for _ in 42u32..21u32 {}
    |              ^^^^^^^^^^^^
@@ -43,5 +43,11 @@ help: consider using the following if you are attempting to iterate over this ra
 LL |     for _ in (21u32..42u32).rev() {}
    |              ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: this range is empty and using it to index a slice will always yield an empty slice
+  --> $DIR/reversed_empty_ranges_fixable.rs:17:18
+   |
+LL |     let _ = &arr[3..3];
+   |              ----^^^^- help: if you want an empty slice, use: `[] as &[i32]`
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/reversed_empty_ranges_unfixable.rs b/tests/ui/reversed_empty_ranges_unfixable.rs
index c9ca4c47668..561a35625f0 100644
--- a/tests/ui/reversed_empty_ranges_unfixable.rs
+++ b/tests/ui/reversed_empty_ranges_unfixable.rs
@@ -9,7 +9,6 @@ fn main() {
     let arr = [1, 2, 3, 4, 5];
     let _ = &arr[3usize..=1usize];
     let _ = &arr[SOME_NUM..1];
-    let _ = &arr[3..3];
 
     for _ in ANSWER..ANSWER {}
 }
diff --git a/tests/ui/reversed_empty_ranges_unfixable.stderr b/tests/ui/reversed_empty_ranges_unfixable.stderr
index 12e5483ecdf..240188cbb46 100644
--- a/tests/ui/reversed_empty_ranges_unfixable.stderr
+++ b/tests/ui/reversed_empty_ranges_unfixable.stderr
@@ -18,17 +18,11 @@ error: this range is reversed and using it to index a slice will panic at run-ti
 LL |     let _ = &arr[SOME_NUM..1];
    |                  ^^^^^^^^^^^
 
-error: this range is empty and using it to index a slice will always yield an empty slice
-  --> $DIR/reversed_empty_ranges_unfixable.rs:12:18
-   |
-LL |     let _ = &arr[3..3];
-   |                  ^^^^
-
 error: this range is empty so it will yield no values
-  --> $DIR/reversed_empty_ranges_unfixable.rs:14:14
+  --> $DIR/reversed_empty_ranges_unfixable.rs:13:14
    |
 LL |     for _ in ANSWER..ANSWER {}
    |              ^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors