Skip to content

Commit

Permalink
Auto merge of rust-lang#118879 - Nadrieril:lint-range-gap, r=estebank
Browse files Browse the repository at this point in the history
Lint singleton gaps after exclusive ranges

In the discussion to stabilize exclusive range patterns (rust-lang#37854), it has often come up that they're likely to cause off-by-one mistakes. We already have the `overlapping_range_endpoints` lint, so I [proposed](rust-lang#37854 (comment)) a lint to catch the complementary mistake.

This PR adds a new `non_contiguous_range_endpoints` lint that catches likely off-by-one errors with exclusive range patterns. Here's the idea (see the test file for more examples):
```rust
match x {
    0..10 => ..., // WARN: this range doesn't match `10_u8` because `..` is an exclusive range
    11..20 => ..., // this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
    _ => ...,
}
// help: use an inclusive range instead: `0_u8..=10_u8`
```

More precisely: for any exclusive range `lo..hi`, if `hi+1` is matched by another range but `hi` isn't, we suggest writing an inclusive range `lo..=hi` instead. We also catch `lo..T::MAX`.
  • Loading branch information
bors committed Mar 9, 2024
2 parents 1bd7383 + 2dd085f commit 6890407
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 19 deletions.
1 change: 1 addition & 0 deletions tests/ui/manual_range_patterns.fixed
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(unused)]
#![allow(non_contiguous_range_endpoints)]
#![warn(clippy::manual_range_patterns)]
#![feature(exclusive_range_pattern)]

Expand Down
1 change: 1 addition & 0 deletions tests/ui/manual_range_patterns.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(unused)]
#![allow(non_contiguous_range_endpoints)]
#![warn(clippy::manual_range_patterns)]
#![feature(exclusive_range_pattern)]

Expand Down
38 changes: 19 additions & 19 deletions tests/ui/manual_range_patterns.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:8:25
--> tests/ui/manual_range_patterns.rs:9:25
|
LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
Expand All @@ -8,109 +8,109 @@ LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
= help: to override `-D warnings` add `#[allow(clippy::manual_range_patterns)]`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:9:25
--> tests/ui/manual_range_patterns.rs:10:25
|
LL | let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:16:25
--> tests/ui/manual_range_patterns.rs:17:25
|
LL | let _ = matches!(f, 1 | (2..=4));
| ^^^^^^^^^^^ help: try: `1..=4`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:17:25
--> tests/ui/manual_range_patterns.rs:18:25
|
LL | let _ = matches!(f, 1 | (2..4));
| ^^^^^^^^^^ help: try: `1..4`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:18:25
--> tests/ui/manual_range_patterns.rs:19:25
|
LL | let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:19:25
--> tests/ui/manual_range_patterns.rs:20:25
|
LL | let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:20:25
--> tests/ui/manual_range_patterns.rs:21:25
|
LL | let _ = matches!(f, 0..=1 | 0..=2 | 0..=3);
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:23:9
--> tests/ui/manual_range_patterns.rs:24:9
|
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
--> tests/ui/manual_range_patterns.rs:26:25
--> tests/ui/manual_range_patterns.rs:27: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
--> tests/ui/manual_range_patterns.rs:28:25
--> tests/ui/manual_range_patterns.rs:29:25
|
LL | let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1_000_001..=1_000_001`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:31:17
--> tests/ui/manual_range_patterns.rs:32:17
|
LL | matches!(f, 0x00 | 0x01 | 0x02 | 0x03);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x03`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:32:17
--> tests/ui/manual_range_patterns.rs:33:17
|
LL | matches!(f, 0x00..=0x05 | 0x06 | 0x07);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x07`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:33:17
--> tests/ui/manual_range_patterns.rs:34:17
|
LL | matches!(f, -0x09 | -0x08 | -0x07..=0x00);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-0x09..=0x00`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:35:17
--> tests/ui/manual_range_patterns.rs:36:17
|
LL | matches!(f, 0..5 | 5);
| ^^^^^^^^ help: try: `0..=5`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:36:17
--> tests/ui/manual_range_patterns.rs:37:17
|
LL | matches!(f, 0 | 1..5);
| ^^^^^^^^ help: try: `0..5`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:38:17
--> tests/ui/manual_range_patterns.rs:39:17
|
LL | matches!(f, 0..=5 | 6..10);
| ^^^^^^^^^^^^^ help: try: `0..10`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:39:17
--> tests/ui/manual_range_patterns.rs:40:17
|
LL | matches!(f, 0..5 | 5..=10);
| ^^^^^^^^^^^^^ help: try: `0..=10`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:40:17
--> tests/ui/manual_range_patterns.rs:41:17
|
LL | matches!(f, 5..=10 | 0..5);
| ^^^^^^^^^^^^^ help: try: `0..=10`

error: this OR pattern can be rewritten using a range
--> tests/ui/manual_range_patterns.rs:44:26
--> tests/ui/manual_range_patterns.rs:45:26
|
LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
Expand Down

0 comments on commit 6890407

Please sign in to comment.