2 //! The **nodrop** crate has the following cargo feature flags:
5 //! - Optional, enabled by default
9 //! - Requires Rust 1.21
10 //! - Use `needs_drop` to skip overwriting if not necessary
13 //! - Requires nightly channel
14 //! - Using untagged union, finally we have an implementation of `NoDrop` without hacks,
15 //! for example the fact that `NoDrop<T>` never has a destructor anymore.
18 #![cfg_attr(not(any(test, feature="std")), no_std)]
19 #[cfg(not(any(test, feature="std")))]
20 extern crate core
as std
;
22 #[cfg(feature = "use_union")]
23 extern crate nodrop_union
as imp
;
28 #[cfg(not(feature = "use_union"))]
32 use std
::ops
::{Deref, DerefMut}
;
34 /// repr(u8) - Make sure the non-nullable pointer optimization does not occur!
38 // Dummy u8 field below, again to beat the enum layout opt
43 /// A type holding **T** that will not call its destructor on drop
44 pub struct NoDrop
<T
>(Flag
<T
>);
47 /// Create a new **NoDrop**.
49 pub fn new(value
: T
) -> NoDrop
<T
> {
50 NoDrop(Flag
::Alive(value
))
53 /// Extract the inner value.
55 /// Once extracted, the value can of course drop again.
57 pub fn into_inner(mut self) -> T
{
61 // skip Drop, so we don't even have to overwrite
67 #[cfg(not(feature = "use_needs_drop"))]
69 fn needs_drop
<T
>() -> bool
{
73 #[cfg(feature = "use_needs_drop")]
75 fn needs_drop
<T
>() -> bool
{
77 ::std
::mem
::needs_drop
::<T
>()
81 impl<T
> Drop
for NoDrop
<T
> {
83 if needs_drop
::<T
>() {
86 ptr
::write(&mut self.0, Flag
::Dropped(0));
92 impl<T
> Deref
for NoDrop
<T
> {
95 // Use type invariant, always Flag::Alive.
97 fn deref(&self) -> &T
{
99 Flag
::Alive(ref inner
) => inner
,
100 _
=> unsafe { debug_assert_unreachable() }
105 impl<T
> DerefMut
for NoDrop
<T
> {
106 // Use type invariant, always Flag::Alive.
108 fn deref_mut(&mut self) -> &mut T
{
110 Flag
::Alive(ref mut inner
) => inner
,
111 _
=> unsafe { debug_assert_unreachable() }
118 fn test_no_nonnullable_opt() {
119 // Make sure `Flag` does not apply the non-nullable pointer optimization
120 // as Option would do.
121 assert
!(mem
::size_of
::<Flag
<&i32>>() > mem
::size_of
::<&i32>());
122 assert
!(mem
::size_of
::<Flag
<Vec
<i32>>>() > mem
::size_of
::<Vec
<i32>>());
125 // copying this code saves us microcrate deps
127 unsafe fn debug_assert_unreachable() -> ! {
128 debug_assert
!(false, "Reached unreachable section: this is a bug!");
130 match *(1 as *const Void
) { }
142 let flag
= &Cell
::new(0);
144 struct Bump
<'a
>(&'a Cell
<i32>);
146 impl<'a
> Drop
for Bump
<'a
> {
148 let n
= self.0.get();
154 let _
= NoDrop
::new([Bump(flag
), Bump(flag
)]);
156 assert_eq
!(flag
.get(), 0);
158 // test something with the nullable pointer optimization
162 let mut array
= NoDrop
::new(Vec
::new());
163 array
.push(vec
![Bump(flag
)]);
164 array
.push(vec
![Bump(flag
), Bump(flag
)]);
166 array
.push(vec
![Bump(flag
)]);
168 assert_eq
!(flag
.get(), 1);
170 assert_eq
!(flag
.get(), 1);
172 assert_eq
!(flag
.get(), 3);
175 // last one didn't drop.
176 assert_eq
!(flag
.get(), 3);
180 let array
= NoDrop
::new(Bump(flag
));
182 assert_eq
!(flag
.get(), 1);
184 assert_eq
!(flag
.get(), 1);