about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-10 00:04:08 +0000
committerbors <bors@rust-lang.org>2023-07-10 00:04:08 +0000
commit9058b040c89b040edf7a4273945a92bd258cb954 (patch)
tree161e64085ba6523f937dacb57e019cbace8b01a2
parent507d1c282e133022666a5a12fcb74a06f2124ecf (diff)
parentc927912c5bc7aa511ca70e5c3786fa0ac8442774 (diff)
downloadrust-9058b040c89b040edf7a4273945a92bd258cb954.tar.gz
rust-9058b040c89b040edf7a4273945a92bd258cb954.zip
Auto merge of #11096 - y21:issue11091, r=giraffate
[`manual_range_patterns`]: lint negative values

Fixes #11091.

Now also lints negative values in patterns (`-1 | -2 | -3`)

changelog: [`manual_range_patterns`]: lint negative values
-rw-r--r--clippy_lints/src/manual_range_patterns.rs24
-rw-r--r--tests/ui/manual_range_patterns.fixed4
-rw-r--r--tests/ui/manual_range_patterns.rs4
-rw-r--r--tests/ui/manual_range_patterns.stderr16
4 files changed, 38 insertions, 10 deletions
diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs
index 65ff555209a..64d4c8e4566 100644
--- a/clippy_lints/src/manual_range_patterns.rs
+++ b/clippy_lints/src/manual_range_patterns.rs
@@ -6,6 +6,7 @@ use rustc_hir::Expr;
 use rustc_hir::ExprKind;
 use rustc_hir::PatKind;
 use rustc_hir::RangeEnd;
+use rustc_hir::UnOp;
 use rustc_lint::LintContext;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
@@ -19,6 +20,10 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// Using an explicit range is more concise and easier to read.
     ///
+    /// ### Known issues
+    /// This lint intentionally does not handle numbers greater than `i128::MAX` for `u128` literals
+    /// in order to support negative numbers.
+    ///
     /// ### Example
     /// ```rust
     /// let x = 6;
@@ -36,11 +41,14 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
 
-fn expr_as_u128(expr: &Expr<'_>) -> Option<u128> {
-    if let ExprKind::Lit(lit) = expr.kind
+fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
+    if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind {
+        expr_as_i128(expr).map(|num| -num)
+    } else if let ExprKind::Lit(lit) = expr.kind
         && let LitKind::Int(num, _) = lit.node
     {
-        Some(num)
+        // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
+        num.try_into().ok()
     } else {
         None
     }
@@ -56,22 +64,22 @@ impl LateLintPass<'_> for ManualRangePatterns {
         if let PatKind::Or(pats) = pat.kind
             && pats.len() >= 3
         {
-            let mut min = u128::MAX;
-            let mut max = 0;
+            let mut min = i128::MAX;
+            let mut max = i128::MIN;
             let mut numbers_found = FxHashSet::default();
             let mut ranges_found = Vec::new();
 
             for pat in pats {
                 if let PatKind::Lit(lit) = pat.kind
-                    && let Some(num) = expr_as_u128(lit)
+                    && let Some(num) = expr_as_i128(lit)
                 {
                     numbers_found.insert(num);
 
                     min = min.min(num);
                     max = max.max(num);
                 } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind
-                    && let Some(left) = expr_as_u128(left)
-                    && let Some(right) = expr_as_u128(right)
+                    && let Some(left) = expr_as_i128(left)
+                    && let Some(right) = expr_as_i128(right)
                     && right >= left
                 {
                     min = min.min(left);
diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed
index 9eee8f37187..6bfcf263aa5 100644
--- a/tests/ui/manual_range_patterns.fixed
+++ b/tests/ui/manual_range_patterns.fixed
@@ -25,6 +25,10 @@ fn main() {
         1..=10 => true,
         _ => false,
     };
+    let _ = matches!(f, -5..=3);
+    let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing
+    let _ = matches!(f, -1000001..=1000001);
+    let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002);
 
     macro_rules! mac {
         ($e:expr) => {
diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs
index 10743a7d04c..4a429bb2aed 100644
--- a/tests/ui/manual_range_patterns.rs
+++ b/tests/ui/manual_range_patterns.rs
@@ -25,6 +25,10 @@ fn main() {
         1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
         _ => false,
     };
+    let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2);
+    let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing
+    let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
+    let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002);
 
     macro_rules! mac {
         ($e:expr) => {
diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr
index bc9e3350164..b1b55d483e7 100644
--- a/tests/ui/manual_range_patterns.stderr
+++ b/tests/ui/manual_range_patterns.stderr
@@ -37,7 +37,19 @@ LL |         1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> $DIR/manual_range_patterns.rs:31:26
+  --> $DIR/manual_range_patterns.rs:28:25
+   |
+LL |     let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-5..=3`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:30:25
+   |
+LL |     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1000001..=1000001`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:35:26
    |
 LL |             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
@@ -47,5 +59,5 @@ LL |     mac!(f);
    |
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors