Closed
Description
This code demonstrates the problem (playpen):
#![allow(dead_code)]
trait Range {
const FIRST: u8;
const LAST: u8;
}
struct OneDigit;
impl Range for OneDigit {
const FIRST: u8 = 0;
const LAST: u8 = 9;
}
struct TwoDigits;
impl Range for TwoDigits {
const FIRST: u8 = 10;
const LAST: u8 = 99;
}
struct ThreeDigits;
impl Range for ThreeDigits {
const FIRST: u8 = 100;
const LAST: u8 = 255;
}
fn digits(x: u8) -> u32 {
match x {
OneDigit::FIRST...OneDigit::LAST => 1,
TwoDigits::FIRST...TwoDigits::LAST => 2,
ThreeDigits::FIRST...ThreeDigits::LAST => 3,
_ => unreachable!(),
}
}
fn main() {
println!("{}", digits(100));
}
With stable-1.32.0 it prints 3
. With beta-1.33.0 it wrongly prints 1
.
Beta also produces these wrong warnings:
warning: unreachable pattern
--> src/main.rs:29:9
|
29 | TwoDigits::FIRST...TwoDigits::LAST => 2,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unreachable_patterns)] on by default
warning: unreachable pattern
--> src/main.rs:30:9
|
30 | ThreeDigits::FIRST...ThreeDigits::LAST => 3,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It seems that Rustc decides, that the first arm covers the whole range of a
u8
and optimizes out the other arms before they even reach MIR.
The code is very similar to this testcase.
But the testcase does not test that the other arms can be reached.
I was able to bisect the regression to #55937.
(This issue seems similar to #57894, but the reduced testcase there does not
use any associated consts)