Rfcs: Precise range exhaustiveness check for match on integer patterns

Created on 21 Mar 2016  路  13Comments  路  Source: rust-lang/rfcs

In theory the compiler should be able to detect that the following range is exhaustive and not error about non-exaustive match:

fn wont_compile(x : u8) { 
    match (x) {
        0x00 ... 0xff => { }
    }
}

Proposed (as a side-portion) in #880

Discussed in https://github.com/rust-lang/rust/issues/12483 and https://github.com/rust-lang/rust/issues/32381

T-lang postponed

Most helpful comment

I have an implementation of this (specifically: interval exhaustiveness checking over integer types). If we need to write up an RFC before integrating it, I'll try to do so in a couple of weeks or so (or if anyone'd like to accelerate the process and write one sooner, that'd be great too)!

Edit: Actually, I'm going to try merged it under a feature flag immediately, as it seems like a straightforward extension to the existing exhaustiveness checks, but it may require an RFC to stabilise.

I've created a tracking issue here: https://github.com/rust-lang/rust/issues/50907 and the pull request is at: https://github.com/rust-lang/rust/pull/50912.

All 13 comments

The following will then error due to _ being unreachable, but it currently is allowed. So we'd need some way to prevent "new" unreachable patterns from being a hard error.

match x {
    0x00...0xFF => {},
    _ => {},
}

@oli-obk We could just warn in that case (and make it a lint so people can #[deny] or #[allow] it, depending on what they want)

Are there any new discussion/plans on this? Adding a warning which can be turned off for legacy code seems like the most elegant solution to me. If that aligns with the consensus, I'd try and take a shot at this during my spring vacation and send a pull request

It's another issue, and likely unsolvable, but this also fails the range exhaustiveness check:

match x & 0x03 {
    0 .. 3 => ..
}

@igor-krawczuk Unreachable patterns have already been downgraded from errors to warnings in https://github.com/rust-lang/rust/pull/38069 I believe, so that sounds reasonable to me.

Perhaps it's time to remove the "postponed" tag.

"match x & 0x03 {}" can be solved with a small amount of value range analysis, that will benefit other parts of Rust.

I'd also like to see discussion start on this again. I ran into this today and was very surprised to see that Rust can't determine that all ranges of a given integer type were covered. I had to add a _ => unreachable!() arm instead.

Determining the completeness of a set of guards/pattern matches over a given domain is a fairly non-trivial problem. I ran into it writing my thesis and it requires applications of the Simplex Algorithm to solve what is effectively a linear programming problem.

It's not impossible to solve, but the complexity of doing so needs to be weighed against the possible ergonomic benefits.

Step 1: perform this conservatively, on integral ranges only and only if there are no guards. This is a common case in low-level code. Benefits: avoided a class of bugs, etc.

Yes, this problem in general is very much non-trivial, but the case outlined by @leonardo-m covers my use case and is certainly doable.

This could be particularly elegant for char:

match c {
    '\u{0000}'..='\u{D7FF}' => ...
    '\u{E000}'..='\u{10_FFFF}' => ...
    // No wildcard needed; all legal USVs are covered
}

I have an implementation of this (specifically: interval exhaustiveness checking over integer types). If we need to write up an RFC before integrating it, I'll try to do so in a couple of weeks or so (or if anyone'd like to accelerate the process and write one sooner, that'd be great too)!

Edit: Actually, I'm going to try merged it under a feature flag immediately, as it seems like a straightforward extension to the existing exhaustiveness checks, but it may require an RFC to stabilise.

I've created a tracking issue here: https://github.com/rust-lang/rust/issues/50907 and the pull request is at: https://github.com/rust-lang/rust/pull/50912.

This has been implemented in https://github.com/rust-lang/rust/pull/50912 as #![feature(exhaustive_integer_patterns)] (tracking issue). We can probably close this issue now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marinintim picture marinintim  路  3Comments

onelson picture onelson  路  3Comments

3442853561 picture 3442853561  路  3Comments

Diggsey picture Diggsey  路  3Comments

torkleyy picture torkleyy  路  3Comments