diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 8e20d3a1dde8b..e26b806dc7397 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2103,8 +2103,7 @@ impl Niche { let distance_end_zero = max_value - v.end; // FIXME: this ought to work for `bool` too, but that seems to be hitting a miscompilation // - let is_bool = size.bytes() == 1 && v == WrappingRange { start: 0, end: 1 }; - if count == 1 && !is_bool { + if count == 1 && v != (WrappingRange { start: 0, end: 1 }) { // We only need one, so just pick the one closest to zero. // Not only does that obviously use zero if it's possible, but it also // simplifies testing things like `Option`, since looking for `-1` diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index 924e2fc6c99ec..ef056769b147d 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -265,7 +265,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } -// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 -1, 2\))?}} %x.0, i16 %x.1) +// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 0, 3\))?}} %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { x diff --git a/tests/ui/codegen/dont-miscompile-enums.rs b/tests/ui/codegen/dont-miscompile-enums.rs new file mode 100644 index 0000000000000..f31a70bf754d6 --- /dev/null +++ b/tests/ui/codegen/dont-miscompile-enums.rs @@ -0,0 +1,43 @@ +//@ run-pass + +// Bad regression test for https://github.com/rust-lang/rust/issues/159035 +// This should probably be replaced with a codegen test, though that might need to be in LLVM, +// as it seems that the miscompilation may occur on correct IR misoptimized by SimplifyCFG. + +#![allow(dead_code)] + +enum Inner { + A(u32), + B(u32), +} +struct Big { + _pad: u64, + inner: Inner, +} +struct Small { + a: u16, + b: u16, + _f: fn(), +} +enum Checksum { + X(Big), + Y(Small), +} +impl Checksum { + fn finalize(self) -> u32 { + match self { + Checksum::X(h) => match h.inner { + Inner::A(s) => s, + Inner::B(s) => s, + }, + Checksum::Y(s) => (u32::from(s.b) << 16) | u32::from(s.a), + } + } +} +#[inline(never)] +fn run(c: Option) -> Option { + c.map(|c| c.finalize()) +} +fn main() { + println!("{:?}", run(std::hint::black_box(None))); +}