diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 78c86a2..d2e3a33 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -55,7 +55,7 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install nightly toolchain + - name: Install beta toolchain uses: actions-rs/toolchain@v1 with: profile: minimal @@ -84,7 +84,7 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install stable toolchain + - name: Install nightly toolchain uses: actions-rs/toolchain@v1 with: toolchain: nightly @@ -96,6 +96,19 @@ jobs: command: test args: --all-features + test-miri: + name: Test Miri + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install Miri + run: | + rustup toolchain install nightly --component miri + rustup override set nightly + cargo miri setup + - name: Test with Miri + run: cargo miri test + build-no-std: name: Build no-std runs-on: ubuntu-latest @@ -113,4 +126,4 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --target thumbv7em-none-eabihf --all-features \ No newline at end of file + args: --target thumbv7em-none-eabihf --all-features diff --git a/src/lib.rs b/src/lib.rs index 13b47de..041514d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -852,6 +852,8 @@ mod tests { } #[test] + #[cfg_attr(miri, ignore)] + // this test takes far too long with Miri enabled fn run_test_push_dequeue_push_full_get_rep() { fn test_push_dequeue_push_full_get_rep(mut rb: impl RingBufferExt) { for _ in 0..100_000 { @@ -973,24 +975,30 @@ mod tests { } macro_rules! test_dropped { - ($constructor: block) => { + ($constructor: block) => {{ + let dt = Box::into_raw(Box::new(RefCell::new(DropTest { flag: false }))); { - let dt = Box::leak(Box::new(RefCell::new(DropTest { flag: false }))); - { - let d = Dropee { parent: Some(dt.borrow_mut()) }; - let mut rb = { $constructor }; - rb.push(d); - rb.push(Dropee { parent: None }); - } - assert!(dt.borrow_mut().flag); - unsafe { - // SAFETY: we know Dropee, which needed the static lifetime, has been dropped (by the assert) - // we could probably skip this, but this makes sure we don't leak any memory - let ptr: *mut RefCell = std::mem::transmute::<&RefCell, _>(dt); - drop(Box::from_raw(ptr)); - } + let d = Dropee { + // Safety: + // We know the pointer is initialized as it was created just above. + // Also no other mutable borrow can exist at this time + parent: Some(unsafe { dt.as_ref() }.unwrap().borrow_mut()), + }; + let mut rb = { $constructor }; + rb.push(d); + rb.push(Dropee { parent: None }); } - }; + { + // Safety: + // We know the pointer exists and is no longer borrowed as the block above limited it + assert!(unsafe { dt.as_ref() }.unwrap().borrow().flag); + } + // Safety: + // No other references exist to box so we can safely drop it + unsafe { + drop(Box::from_raw(dt)); + } + }}; } #[test]