-
Notifications
You must be signed in to change notification settings - Fork 123
Description
Hello @myrrlyn
bitvec: v1.0.1
I think I stumbled upon a strange and nasty bug, where the outcome is different in rustc DEV versus RELEASE compilation profile.
The minimal test example which passes in DEV while fails in RELEASE:
use std::cell::Cell;
use bitvec::prelude::*;
#[test]
fn test_cell_bitvec() {
let cell: Cell<u8> = Cell::new(0);
for index in 0..8 {
assert_eq!(*cell.view_bits::<Lsb0>().get(index).unwrap(), false);
}
for index in 0..8 {
cell.view_bits::<Lsb0>().set_aliased(index, true);
}
for index in 0..8 {
assert_eq!(*cell.view_bits::<Lsb0>().get(index).unwrap(), true);
}
}
#[test]
fn test_cell_bitvec_unchecked() {
let cell: Cell<u8> = Cell::new(0);
for index in 0..8 {
assert_eq!(*unsafe { cell.view_bits::<Lsb0>().get_unchecked(index) }, false);
}
for index in 0..8 {
unsafe { cell.view_bits::<Lsb0>().set_aliased_unchecked(index, true) }
}
for index in 0..8 {
assert_eq!(*unsafe { cell.view_bits::<Lsb0>().get_unchecked(index) }, true);
}
}
When tested with --release
flag both tests fail as if set_alias
and set_alias_unchecked
was never called:
running 2 tests
test tests::test_cell_bitvec ... FAILED
test tests::test_cell_bitvec_unchecked ... FAILED
failures:
---- tests::test_cell_bitvec stdout ----
thread 'tests::test_cell_bitvec' panicked at src/main.rs:36:13:
assertion `left == right` failed
left: false
right: true
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- tests::test_cell_bitvec_unchecked stdout ----
thread 'tests::test_cell_bitvec_unchecked' panicked at src/main.rs:53:13:
assertion `left == right` failed
left: false
right: true
failures:
tests::test_cell_bitvec
tests::test_cell_bitvec_unchecked
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
If I replace Cell<u8>
with any other primitive type: Cell<u16|u32|u64|usize>
the test does not fail in RELEASE mode. This only happens for Cell<u8>
!
The only workaround I found so far is to replace Cell<u8>
with AtomicU8
which is not ideal as I'm using it in a single threaded environment.
This happens regardless of the platform, as I first detected the problem on thumbv7em
but later I confirmed the same is happening on x86_64
.
The bug is quite nasty and can give you headaches when trying to debug this, especially that it works fine in DEV and only manifests when optimizations are turned on.
Moreover it does not matter what kind of opt-level
is enabled as long as it's equal to or above opt-level = 1
for profile.release
.