Description
Code
I tried this code:
pub fn f(a: Option<u32>) -> u32 {
match a {
None => {}
Some(_) => unsafe { std::hint::unreachable_unchecked() }
}
a.unwrap()
}
I expected to see this happen: no branch instructions emitted, unreachable_unchecked
makes an assumption that a
is None
, so unwrap
should be inlined and optimized as a panic.
Instead, this happened: there is a discriminant check still emitted.
Version it worked on
It most recently worked on: nightly-2023-03-26
Version with regression
; rustc +nightly-2023-03-27 --version --verbose
rustc 1.70.0-nightly (db0cbc48d 2023-03-26)
binary: rustc
commit-hash: db0cbc48d4aaa300713a95d9b317a365a474490c
commit-date: 2023-03-26
host: aarch64-unknown-linux-gnu
release: 1.70.0-nightly
LLVM version: 16.0.0
ASM diff
See godbolt: https://godbolt.org/z/5WKTY99Te
Bisection results
Regression occurred in #106428 (cc @saethlin).
searched nightlies: from nightly-2023-03-01 to nightly-2023-04-01
regressed nightly: nightly-2023-03-27
searched commit range: 0c61c7a...db0cbc4
regressed commit: 2420bd3
bisected with cargo-bisect-rustc v0.6.6
Host triple: aarch64-unknown-linux-gnu
Reproduce with:
cargo bisect-rustc --start=2023-03-01 --end=2023-04-01 --regress=success --script=./t.sh
t.sh
#!/bin/sh
set -ex
rustc t.rs --crate-type=lib --emit=asm -O && cat ./t.s | grep -E "cbz\s+w0, .LBB0_2"
(if you want to test on x86_64
replace "cbz\s+w0, .LBB0_2"
with "testl\s+%edi, %edi"
)
t.rs
pub fn f(a: Option<i32>) -> i32 {
unsafe { if !a.is_none() { std::hint::unreachable_unchecked() } }
return a.unwrap();
}
History
@heckad originally noticed the problem and opened #110456, then @WaffleLapkin suggested that this is a compiler issue, then @bugadani noticed that this is a regression, then @WaffleLapkin bisected and opened this issue.