rust-lang / rust-lang/rust-clippy

Integer range pattern clarity

Open
#10,397 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lint
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

What it does

This lint discourages potentially-confusing integer range patterns. I'm opening an issue instead of a pull request because I'm not sure exactly what the rules should be, but here's my first pass:

  • If a wildcard pattern can be replaced with a pattern in the form z.., do so.
  • If two consecutive patterns leave a gap of width exactly 1 between them, and the first one is an exclusive range, suggest an inclusive range instead.
  • Alternatively, if there's a wildcard pattern figure out exactly what explicit pattern would replace it and suggest that.
Lint Name

range_pattern_readability

Category

suspicious, style

Advantage

This lint idea is inspired by concerns brought up in rust#37854. I've come to believe that using wildcard patterns alongside integer range patterns leads to poor diagnostics. For instance I would suggest that a match like in foo1 below is probably a mistake, but it doesn't trigger an incomplete-match error the way foo2 does because of the wildcard pattern. foo0 doesn't look like a mistake, but I think replacing the wildcard with a half-open range pattern leads to better readability and better confidence that an incomplete-match error isn't being incorrectly suppressed. Having a lint like this would alleviate some of the concerns about stabilizing the exclusive_range_pattern feature.

Drawbacks

There are several problems that need to be overcome with this lint. First is the issue of figuring out exactly what the rules should be: when should the lint trigger, and how complex of a final pattern should it suggest before it gets ridiculous? How can we make sure this lint improves readability instead of degrading it? Then there's the problem with signed integers: specifically that ..z patterns are still unstable and will likely be stabilized separately from a..b patterns. That's not such a problem because ..=z patterns are already stable, but it complicates things. Finally there's the fact that match exhaustiveness is currently broken for point-sized integer types (rust#56354). As far as I can tell rustc currently requires any match involving a pointer-sized integer to have a wildcard pattern, so we won't be able to apply this lint to those types until that issue is resolved.

Example
#![feature(exclusive_range_pattern)]

fn foo0(x: u32) -> u32 {
    match x {
        0..10 => 0,
        10..20 => 10,
        _ => 20,
    }
}

fn foo1(x: u32) -> u32 {
    match x {
        0..9 => 0,
        10..19 => 10,
        _ => 20,
    }
}

fn foo2(x: u32) -> u32 {
    match x {
        0..9 => 0,      // }
        10..19 => 10,   // }-- this is already an error
        20.. => 20,     // }
    }
}

Could be written as:

#![feature(exclusive_range_pattern)]

fn foo0(x: u32) -> u32 {
    match x {
        0..10 => 0,
        10..20 => 10,
        20.. => 20,
    }
}

fn foo1a(x: u32) -> u32 {
    match x {
        0..=9 => 0,
        10..=19 => 10,
        20.. => 20,
    }
}

fn foo1b(x: u32) -> u32 {
    match x {
        0..9 => 0,
        10..19 => 10,
        9 | 19.. => 20,
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no implementation files or tests; start with the proposed range_pattern_readability rules and the foo0, foo1, and foo2 examples. Resolve the open design questions around wildcard replacement, signed integers, and pointer-sized integers before implementation. Done means agreed lint behavior and diagnostics that address the examples without the stated exhaustiveness limitations.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.