diff options
Diffstat (limited to 'third_party/rust/nodrop')
-rw-r--r-- | third_party/rust/nodrop/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/nodrop/Cargo.toml | 33 | ||||
-rw-r--r-- | third_party/rust/nodrop/README.rst | 58 | ||||
-rw-r--r-- | third_party/rust/nodrop/src/lib.rs | 186 |
4 files changed, 278 insertions, 0 deletions
diff --git a/third_party/rust/nodrop/.cargo-checksum.json b/third_party/rust/nodrop/.cargo-checksum.json new file mode 100644 index 0000000000..ccf2b11d44 --- /dev/null +++ b/third_party/rust/nodrop/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"518e2e6cea4cec4804a6fc04c8138a2db95783cbc13e0b49526553232f7b9699","README.rst":"68844a4fd6edead8ecd0c0053a8618f89fc5bbe8bc1ee000808358f6f0f4d8ff","src/lib.rs":"96d5ddaf03ccbdff8ddcd79b5fdc015aad4451a8d76d0b9a94dff14f49e2dcc9"},"package":"9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"}
\ No newline at end of file diff --git a/third_party/rust/nodrop/Cargo.toml b/third_party/rust/nodrop/Cargo.toml new file mode 100644 index 0000000000..d1a5f4a861 --- /dev/null +++ b/third_party/rust/nodrop/Cargo.toml @@ -0,0 +1,33 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "nodrop" +version = "0.1.12" +authors = ["bluss"] +description = "A wrapper type to inhibit drop (destructor). Use std::mem::ManuallyDrop instead!" +documentation = "https://docs.rs/nodrop/" +keywords = ["container", "drop", "no_std"] +categories = ["rust-patterns"] +license = "MIT/Apache-2.0" +repository = "https://github.com/bluss/arrayvec" +[package.metadata.release] +no-dev-version = true +[dependencies.nodrop-union] +version = "0.1.8" +optional = true + +[features] +std = [] +use_union = ["nodrop-union"] +use_needs_drop = [] +default = ["std"] diff --git a/third_party/rust/nodrop/README.rst b/third_party/rust/nodrop/README.rst new file mode 100644 index 0000000000..401a4a6a15 --- /dev/null +++ b/third_party/rust/nodrop/README.rst @@ -0,0 +1,58 @@ + +nodrop +====== + +Recent Changes (nodrop) +----------------------- + +- 0.1.12 + + - Remove dependency on crate odds. + +- 0.1.11 + + - Remove erronous assertion in test (#77) + +- 0.1.10 + + - Update for stable ``needs_drop`` (Rust 1.21, was nightly only) + +- 0.1.9 + + - Fix issue in recent nightly where ``repr(u8)`` did not work. Use + a better way to get rid of the enum layout optimization. + +- 0.1.8 + + - Add crate feature ``use_union`` that uses untagged unions to implement NoDrop. + Finally we have an implementation without hacks, without a runtime flag, + and without an actual ``Drop`` impl (which was needed to suppress drop). + The crate feature requires nightly and is unstable. + +- 0.1.7 + + - Remove crate feature ``no_drop_flag``, because it doesn't compile on nightly + anymore. Drop flags are gone anyway! + +- 0.1.6 + + - Add feature std, which you can opt out of to use ``no_std``. + +- 0.1.5 + + - Added crate feature ``use_needs_drop`` which is a nightly-only + optimization, which skips overwriting if the inner value does not need + drop. + +License +======= + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +http://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. + + diff --git a/third_party/rust/nodrop/src/lib.rs b/third_party/rust/nodrop/src/lib.rs new file mode 100644 index 0000000000..433905e3fa --- /dev/null +++ b/third_party/rust/nodrop/src/lib.rs @@ -0,0 +1,186 @@ +//! +//! The **nodrop** crate has the following cargo feature flags: +//! +//! - `std` +//! - Optional, enabled by default +//! - Use libstd +//! - `use_needs_drop` +//! - Optional +//! - Requires Rust 1.21 +//! - Use `needs_drop` to skip overwriting if not necessary +//! - `use_union` +//! - Optional +//! - Requires nightly channel +//! - Using untagged union, finally we have an implementation of `NoDrop` without hacks, +//! for example the fact that `NoDrop<T>` never has a destructor anymore. +//! + +#![cfg_attr(not(any(test, feature="std")), no_std)] +#[cfg(not(any(test, feature="std")))] +extern crate core as std; + +#[cfg(feature = "use_union")] +extern crate nodrop_union as imp; + +pub use imp::NoDrop; + + +#[cfg(not(feature = "use_union"))] +mod imp { + use std::ptr; + use std::mem; + use std::ops::{Deref, DerefMut}; + + /// repr(u8) - Make sure the non-nullable pointer optimization does not occur! + #[repr(u8)] + enum Flag<T> { + Alive(T), + // Dummy u8 field below, again to beat the enum layout opt + Dropped(u8), + } + + + /// A type holding **T** that will not call its destructor on drop + pub struct NoDrop<T>(Flag<T>); + + impl<T> NoDrop<T> { + /// Create a new **NoDrop**. + #[inline] + pub fn new(value: T) -> NoDrop<T> { + NoDrop(Flag::Alive(value)) + } + + /// Extract the inner value. + /// + /// Once extracted, the value can of course drop again. + #[inline] + pub fn into_inner(mut self) -> T { + let inner = unsafe { + ptr::read(&mut *self) + }; + // skip Drop, so we don't even have to overwrite + mem::forget(self); + inner + } + } + + #[cfg(not(feature = "use_needs_drop"))] + #[inline] + fn needs_drop<T>() -> bool { + true + } + + #[cfg(feature = "use_needs_drop")] + #[inline] + fn needs_drop<T>() -> bool { + unsafe { + ::std::mem::needs_drop::<T>() + } + } + + impl<T> Drop for NoDrop<T> { + fn drop(&mut self) { + if needs_drop::<T>() { + // inhibit drop + unsafe { + ptr::write(&mut self.0, Flag::Dropped(0)); + } + } + } + } + + impl<T> Deref for NoDrop<T> { + type Target = T; + + // Use type invariant, always Flag::Alive. + #[inline] + fn deref(&self) -> &T { + match self.0 { + Flag::Alive(ref inner) => inner, + _ => unsafe { debug_assert_unreachable() } + } + } + } + + impl<T> DerefMut for NoDrop<T> { + // Use type invariant, always Flag::Alive. + #[inline] + fn deref_mut(&mut self) -> &mut T { + match self.0 { + Flag::Alive(ref mut inner) => inner, + _ => unsafe { debug_assert_unreachable() } + } + } + } + + #[cfg(test)] + #[test] + fn test_no_nonnullable_opt() { + // Make sure `Flag` does not apply the non-nullable pointer optimization + // as Option would do. + assert!(mem::size_of::<Flag<&i32>>() > mem::size_of::<&i32>()); + assert!(mem::size_of::<Flag<Vec<i32>>>() > mem::size_of::<Vec<i32>>()); + } + + // copying this code saves us microcrate deps + #[inline] + unsafe fn debug_assert_unreachable() -> ! { + debug_assert!(false, "Reached unreachable section: this is a bug!"); + enum Void { } + match *(1 as *const Void) { } + } +} + +#[cfg(test)] +mod tests { + use super::NoDrop; + + #[test] + fn test_drop() { + use std::cell::Cell; + + let flag = &Cell::new(0); + + struct Bump<'a>(&'a Cell<i32>); + + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + } + } + + { + let _ = NoDrop::new([Bump(flag), Bump(flag)]); + } + assert_eq!(flag.get(), 0); + + // test something with the nullable pointer optimization + flag.set(0); + + { + let mut array = NoDrop::new(Vec::new()); + array.push(vec![Bump(flag)]); + array.push(vec![Bump(flag), Bump(flag)]); + array.push(vec![]); + array.push(vec![Bump(flag)]); + drop(array.pop()); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 3); + } + + // last one didn't drop. + assert_eq!(flag.get(), 3); + + flag.set(0); + { + let array = NoDrop::new(Bump(flag)); + array.into_inner(); + assert_eq!(flag.get(), 1); + } + assert_eq!(flag.get(), 1); + } +} |