-
Notifications
You must be signed in to change notification settings - Fork 128
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.