Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ categories = ["concurrency", "no-std", "rust-patterns"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
maybe-dangling = "0.1.2"

[dev-dependencies]
once_cell = "1.8.0"
21 changes: 20 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@
#![no_std]
use core::{
cell::UnsafeCell,
mem::ManuallyDrop,
sync::atomic::{AtomicBool, Ordering},
};
use maybe_dangling::ManuallyDrop;

/// A cell type which value can be taken only once.
///
Expand Down Expand Up @@ -320,6 +320,8 @@ unsafe impl<T: ?Sized + Send> Sync for TakeCell<T> {}
#[derive(Default)]
pub struct TakeOwnCell<T>(
// Invariant: `TakeCell::taken` is true <=> `ManuallyDrop`'s value was taken
// Note that we're using `ManuallyDrop` from the `maybe-dangling` crate,
// in order to avoid the unsoundness in https://github.com/WaffleLapkin/takecell/issues/5
TakeCell<ManuallyDrop<T>>,
);

Expand Down Expand Up @@ -602,6 +604,8 @@ mod tests {
#[cfg(test)]
mod own_tests {
use crate::TakeOwnCell;
extern crate alloc;
use alloc::boxed::Box;

#[test]
fn it_works() {
Expand Down Expand Up @@ -659,4 +663,19 @@ mod own_tests {
assert!(cell.take().is_none());
assert!(cell.into_inner().is_none());
}

// Moving an empty `TakeOwnCell` should not assert validity or ownership
// of its former contents.
// See https://github.com/WaffleLapkin/takecell/issues/5
#[test]
fn maybe_dangling() {
let cell = TakeOwnCell::new(Box::new(1));
let data = cell.take().unwrap();
// Moving the cell does not invalidate the data
let cell = cell;
assert_eq!(*data, 1);
// Dropping the data does not invalidate the cell
drop(data);
let _cell = cell;
}
}