[manual_range_patterns]: lint negative values

This commit is contained in:
y21 2023-07-03 20:24:14 +02:00
parent 26edd5a2ab
commit 5cc0c04826
4 changed files with 33 additions and 10 deletions

View file

@ -6,6 +6,7 @@ use rustc_hir::Expr;
use rustc_hir::ExprKind; use rustc_hir::ExprKind;
use rustc_hir::PatKind; use rustc_hir::PatKind;
use rustc_hir::RangeEnd; use rustc_hir::RangeEnd;
use rustc_hir::UnOp;
use rustc_lint::LintContext; use rustc_lint::LintContext;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
@ -36,11 +37,13 @@ declare_clippy_lint! {
} }
declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
fn expr_as_u128(expr: &Expr<'_>) -> Option<u128> { fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
if let ExprKind::Lit(lit) = expr.kind 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 && let LitKind::Int(num, _) = lit.node
{ {
Some(num) Some(num as i128)
} else { } else {
None None
} }
@ -56,22 +59,22 @@ impl LateLintPass<'_> for ManualRangePatterns {
if let PatKind::Or(pats) = pat.kind if let PatKind::Or(pats) = pat.kind
&& pats.len() >= 3 && pats.len() >= 3
{ {
let mut min = u128::MAX; let mut min = i128::MAX;
let mut max = 0; let mut max = i128::MIN;
let mut numbers_found = FxHashSet::default(); let mut numbers_found = FxHashSet::default();
let mut ranges_found = Vec::new(); let mut ranges_found = Vec::new();
for pat in pats { for pat in pats {
if let PatKind::Lit(lit) = pat.kind 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); numbers_found.insert(num);
min = min.min(num); min = min.min(num);
max = max.max(num); max = max.max(num);
} else if let PatKind::Range(Some(left), Some(right), end) = pat.kind } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind
&& let Some(left) = expr_as_u128(left) && let Some(left) = expr_as_i128(left)
&& let Some(right) = expr_as_u128(right) && let Some(right) = expr_as_i128(right)
&& right >= left && right >= left
{ {
min = min.min(left); min = min.min(left);

View file

@ -25,6 +25,10 @@ fn main() {
1..=10 => true, 1..=10 => true,
_ => false, _ => 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 { macro_rules! mac {
($e:expr) => { ($e:expr) => {

View file

@ -25,6 +25,10 @@ fn main() {
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
_ => false, _ => 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 { macro_rules! mac {
($e:expr) => { ($e:expr) => {

View file

@ -37,7 +37,19 @@ LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
error: this OR pattern can be rewritten using a range 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) LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=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) = 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