safe_manually_drop/
_lib.rs

1//! [SafeManuallyDrop]: `SafeManuallyDrop`
2//! [`SafeManuallyDrop`]: `SafeManuallyDrop`
3//! [`SafeManuallyDrop::into_inner_defusing_impl_Drop()`]: `SafeManuallyDrop::into_inner_defusing_impl_Drop()`
4//! [`DropManually`]: `DropManually`
5//! [`DropManually::drop_manually()`]: `DropManually::drop_manually()`
6//! [`appendix`]: `appendix`
7//!
8//! [`ManuallyDrop`]: `ManuallyDrop`
9//! [`::core::ops::Deref`]: `::core::ops::Deref`
10//! [`::core::ops::DerefMut`]: `::core::ops::DerefMut`
11//! [`Drop`]: `Drop`
12//! [`Option`]: `Option`
13//! [`From::from()`]: `From::from()`
14#![doc = include_str!("../README.md")]
15#![cfg_attr(not(doc), no_std)]
16#![allow(unused_braces)]
17#![cfg_attr(feature = "better-docs", feature(doc_cfg))]
18
19use ::core::{
20    marker::PhantomData as PD,
21    mem::{ManuallyDrop, ManuallyDrop as MD},
22};
23
24#[cfg(doc)]
25#[cfg_attr(feature = "better-docs", doc(cfg(doc)))]
26#[doc = include_str!("appendix.md")]
27pub mod appendix {}
28
29/// The crate's prelude.
30pub
31mod prelude {
32    #[doc(no_inline)]
33    pub use crate::{
34        DropManually,
35        SafeManuallyDrop,
36    };
37}
38
39/// The main/whole point of this whole crate and design: to expose _owned_ access to a `FieldTy`
40/// when drop glue is being run.
41///
42///   - A [`SafeManuallyDrop<FieldTy, ContainingType>`],
43///   - with a (mandatory)
44///     <code>impl [DropManually\<FieldTy\>][`DropManually`] for ContainingType {</code>,
45///   - once it gets dropped / during its drop glue (_e.g._, from within a `ContainingType`),
46///   - shall be running the [`DropManually::drop_manually()`] logic on that _owned_ `FieldTy`.
47///
48/// In practice, this becomes _the_ handy, 0-runtime-overhead, non-`unsafe`, tool to get owned
49/// access to a `struct`'s field (or group thereof) during drop glue.
50///
51/// Indeed, the recipe then becomes:
52///
53///  1. Use, instead of a `field: FieldTy`, a wrapped
54///     <code>field: [SafeManuallyDrop]\<FieldTy, ContainingType\></code>,
55///
56///       - (Usually `Self` can be used instead of having to spell out, _verbatim_, the
57///         `ContainingType`.)
58///
59///       - (This wrapper type offers transparent
60///         <code>[Deref][`::core::ops::Deref`]{,[Mut][`::core::ops::DerefMut`]}</code>, as well as
61///         [`From::from()`] and ["`.into()`"][`SafeManuallyDrop::into_inner_defusing_impl_Drop()`]
62///         conversions.)
63///
64///  1. then, provide the companion, mandatory,
65///     <code>impl [DropManually\<FieldTy\>][`DropManually`] for ContainingType {</code>
66///
67///  1. Profit™ from the owned access to `FieldTy` inside of [`DropManually::drop_manually()`]'s
68///     body.
69///
70/// ### "`OverrideDropGlue`" rather than `PrependDropGlue`
71///
72/// Note that this new drop glue logic for `FieldTy`, defined in [`DropManually::drop_manually()`],
73/// shall _supersede_ / override its default drop glue.
74///
75/// ```rust
76/// use ::safe_manually_drop::prelude::*;
77///
78/// pub struct MyType(SafeManuallyDrop<String, Self>);
79///
80/// impl DropManually<String> for MyType {
81///     fn drop_manually(s: String) {
82///         // stuff…
83///     } // <- unless `s` has been moved out (e.g., though `mem::forget()`),
84///       //    `s`' own drop glue (e.g., here, that of `String`) gets automagically
85///       //    invoked, rather similarly to the classic `Drop` trait.
86///       //    But the huge difference is that this function body had to *allow* it
87///       //    to happen, by not having *consumed* the owned `s: String` in some other
88///       //    way.
89/// }
90///
91/// fn example(it: MyType) {
92///     drop(it); // invokes the drop glue of `MyType`,
93///               // i.e., the `Drop` impl `for SafeManuallyDrop<String, MyType>`
94///               // i.e., `<MyType as DropManually<String>>::drop_manually()`.
95/// }
96/// ```
97///
98/// For instance: if, inside of [`DropManually::drop_manually()`], the `FieldTy` is
99/// [`::core::mem::forget()`]ten, then `FieldTy`'s own drop glue shall never actually run, much like
100/// when a [`ManuallyDrop<FieldTy>`] is [`drop()`]-ped/discarded.
101///
102/// With that being said, precisely because [`DropManually::drop_manually()`] receives an owned
103/// instance of `FieldTy`, this behavior is rather "opt-out": that `FieldTy` owned instance runs
104/// out of scope when the function completes, so it will almost always get "dropped" / have its own
105/// drop glue being invoked.
106///
107/// The only exceptions are then when other, ownership-consuming, functions, get called on this
108/// value.
109///
110/// Typically:
111///
112///   - [`::core::mem::forget()`] to skip/bypass all of the drop glue altogether.
113///       - note that a direct [`ManuallyDrop<FieldTy>`] would probably be better in this instance;
114///   - an `impl FnOnce()` getting called (the `()`-call consumes ownership);
115///   - an owned argument `S` is fed to a function, such as `S` in an `impl FnOnce(S)`;
116///   - types using owned type-state patterns, most notably `Transaction::{commit,roll_back}()`.
117#[diagnostic::on_unimplemented(
118    note = "\
119In order for a struct/enum to contain a `SafeManuallyDrop<FieldTy, …>` field:
120
121 1. `…`, the second type parameter, ought to be `Self`, i.e., the containing `struct/enum` \
122    wherein the provided `DropManually` logic makes sense.
123
124    For instance:
125
126    ```rust
127    field: SafeManuallyDrop<FieldTy, Self>,
128    ```
129
130 2. you then have to provide an \
131    `impl<…> DropManually<FieldTy> for <the containing struct/enum> {{`.
132
133    For instance:
134
135    ```rust
136    impl<…> DropManually<FieldTy> for StructName<…> {{
137    ```
138\
139    ",
140)]
141pub
142trait DropManually<FieldTy> {
143    fn drop_manually(_: FieldTy);
144}
145
146/// [`SafeManuallyDrop<FieldTy>`] is the safe counterpart of [`ManuallyDrop<FieldTy>`], and the
147/// zero-runtime-overhead counterpart of [`Option<FieldTy>`].
148///
149/// ## Example
150///
151///   - Using [`ManuallyDrop<FieldTy>`] and `unsafe`:
152///
153///     ```rust
154///     #![deny(unsafe_code)] // require visible `#[allow()]`s in subtle functions.
155///
156///     use ::core::mem::ManuallyDrop;
157///
158///     pub
159///     struct DeferGuard<T, F : FnOnce(T)> {
160///         value: ManuallyDrop<T>,
161///         on_drop: ManuallyDrop<F>,
162///     }
163///
164///     impl<T, F : FnOnce(T)> Drop for DeferGuard<T, F> {
165///         fn drop(&mut self) {
166///             #[allow(unsafe_code)] {
167///                 let value = unsafe { // 😰
168///                     ManuallyDrop::take(&mut self.value)
169///                 };
170///                 let on_drop = unsafe { // 😰
171///                     ManuallyDrop::take(&mut self.on_drop)
172///                 };
173///                 on_drop(value);
174///             }
175///         }
176///     }
177///
178///     impl<T, F : FnOnce(T)> ::core::ops::Deref for DeferGuard<T, F> {
179///         type Target = T;
180///
181///         fn deref(&self) -> &T {
182///             &self.value
183///         }
184///     }
185///     // And `DerefMut`
186///     ```
187///
188///   - Using [`Option<FieldTy>`] and [`.unwrap()`][`Option::unwrap()`]s everywhere…
189///
190///     ```rust
191///     #![forbid(unsafe_code)]
192///
193///     struct DeferGuardFields<T, F : FnOnce(T)> {
194///         value: T,
195///         on_drop: F,
196///     }
197///
198///     pub
199///     struct DeferGuard<T, F : FnOnce(T)>(
200///         Option<DeferGuardFields<T, F>>,
201///     );
202///
203///     impl<T, F : FnOnce(T)> Drop for DeferGuard<T, F> {
204///         fn drop(&mut self) {
205///             let DeferGuardFields {
206///                 value,
207///                 on_drop,
208///             } = self.0.take().unwrap(); // 🤢
209///             on_drop(value);
210///         }
211///     }
212///
213///     impl<T, F : FnOnce(T)> ::core::ops::Deref for DeferGuard<T, F> {
214///         type Target = T;
215///
216///         fn deref(&self) -> &T {
217///             &self
218///                 .0
219///                 .as_ref()
220///                 .unwrap() // 🤮
221///                 .value
222///         }
223///     }
224///     // And `DerefMut`
225///     ```
226///
227///   - Using [`SafeManuallyDrop<FieldTy, …>`][`SafeManuallyDrop`]: no `unsafe`, no `.unwrap()`s!
228///
229///     ```rust
230///     #![forbid(unsafe_code)]
231///
232///     use ::safe_manually_drop::{DropManually, SafeManuallyDrop};
233///
234///     struct DeferGuardFields<T, F : FnOnce(T)> {
235///         value: T,
236///         on_drop: F,
237///     }
238///
239///     pub
240///     struct DeferGuard<T, F : FnOnce(T)>(
241///      // rather than `Option<DeferGuardFields<T, F>>`,
242///      // or `ManuallyDrop<DeferGuardFields<T, F>>`, use:
243///         SafeManuallyDrop<DeferGuardFields<T, F>, Self>,
244///     );
245///
246///     impl<T, F : FnOnce(T)>
247///         DropManually<DeferGuardFields<T, F>>
248///     for
249///         DeferGuard<T, F>
250///     {
251///         fn drop_manually(
252///             DeferGuardFields { value, on_drop }: DeferGuardFields<T, F>,
253///         )
254///         {
255///             on_drop(value);
256///         }
257///     }
258///
259///     impl<T, F : FnOnce(T)> ::core::ops::Deref for DeferGuard<T, F> {
260///         type Target = T;
261///
262///         fn deref(&self) -> &T {
263///             &self.0.value
264///         }
265///     }
266///     // And `DerefMut`
267///     ```
268///
269/// ## Explanation
270///
271/// It manages to be non-`unsafe`, w.r.t. [`ManuallyDrop<FieldTy>`], by virtue of having a
272/// significantly more restricted use case: that of being used as a `struct`[^or_enum]'s field,
273/// and merely **exposing _owned_ access to the `FieldTy` on _drop_**.
274///
275/// [^or_enum]: (or `enum`, but for the remainder of the explanation, I will stick to talking of
276/// `struct`s exclusively, since it's simpler.)
277///
278/// Such owned access, and _drop_ logic, is exposed and defined in the companion
279/// [`DropManually<FieldTy>`] trait.
280///
281/// In such an `impl`, you shall only have access to that `FieldTy`:
282///
283///   - no access to sibling field types,
284///
285///     (this can be trivially worked around by bundling all the necessary fields together inside
286///     the [`SafeManuallyDrop<_>`]; _c.f._ the example above with the `DeferGuardFields` helper
287///     definition;)
288///
289///   - nor to the encompassing `struct` altogether.
290///
291/// The latter is kind of problematic, since the desired drop glue logic is probably strongly tied
292/// to such encompassing `struct`.
293///
294/// Hence that second generic type parameter on [`SafeManuallyDrop<FieldTy, ContainingType>`].
295///
296/// As its name indicates, it is expected to be the containing/encompassing `struct`:
297///
298/// ```rust
299/// use ::safe_manually_drop::SafeManuallyDrop;
300///
301/// struct Example {
302///     //       ^
303///     //       +-----------------------+
304///     //                               |
305///     string: SafeManuallyDrop<String, Self>,
306/// }
307/// #
308/// # impl ::safe_manually_drop::DropManually<String> for Example {
309/// #     fn drop_manually(_: String) {}
310/// # }
311/// ```
312///
313/// That way, this containing `struct` can be used as the `Self`/`impl`ementor type for the drop
314/// glue:
315///
316/// ```rust
317/// use ::safe_manually_drop::DropManually;
318///
319/// # struct Example {
320/// #    //       ^
321/// #    //       +-----------------------+
322/// #    //                               |
323/// #    string: ::safe_manually_drop::SafeManuallyDrop<String, Self>,
324/// # }
325/// #
326/// impl DropManually<String> for Example {
327///     fn drop_manually(s: String) {
328///         // owned access to `s` here!
329///         # let random = || true; // determined by faire dice roll.
330///         if random() {
331///             drop(s);
332///         } else {
333///             ::core::mem::forget(s);
334///         }
335///     }
336/// }
337/// ```
338///
339/// ## Going further
340///
341/// In practice, neither the API of this crate, nor that of any non-macro API for that matter, can
342/// ever hope to check, impose, nor control that the `ContainingType` used for a
343/// [`SafeManuallyDrop<FieldTy, ContainingType>`] do match that of the containing `struct`.
344///
345/// And, as a matter of fact, there may even be legitimate cases where you may do so on purpose.
346///
347/// Indeed, this extra type parameter is, at the end of the day, a mere `impl DropManually`
348/// "identifier" / discriminant for it to be possible for anybody to write such impls for arbitrary
349/// `FieldTy` types, even when the `FieldTy` is a fully unconstrained/blanket `<T>/<F>` generic
350/// type, and/or when it stems from an upstream crate, or even when wanting to repeat
351/// `SafeManuallyDrop<FieldTy, …>` multiple types within the same `struct`.
352///
353/// In such a case, you may want distinct drop logic for one field _vs._ another.
354///
355/// If so, then consider/notice how what that `ContainingType` _actually_ is, is rather a
356/// `DropImplIdentifier/DropImplDiscriminant/DropStrategy` mere `PhantomData`-like type parameter.
357///
358/// Which means that in this context, you will likely want to involve dedicated phantom types for
359/// the `ContainingType, FieldIdentifier` pair:
360///
361/// ```rust
362/// use ::safe_manually_drop::prelude::*;
363///
364/// use some_lib::Transaction;
365/// // where `some_lib` has the following API, say:
366/// mod some_lib {
367///     pub struct Transaction(());
368///
369///     // Owned `self` receivers for stronger type-level guarantees.
370///     impl Transaction {
371///         pub fn commit(self) {}
372///         pub fn roll_back(self) {}
373///     }
374/// }
375///
376/// enum MyType {
377///     AutoCommitOnDrop {
378///         txn: SafeManuallyDrop<Transaction, CommitOnDropStrategy>,
379///     },
380///
381///     AutoRollBackOnDrop {
382///         txn: SafeManuallyDrop<Transaction, RollBackOnDropStrategy>,
383///     },
384/// }
385///
386/// enum CommitOnDropStrategy {}
387/// impl DropManually<Transaction> for CommitOnDropStrategy {
388///     fn drop_manually(txn: Transaction) {
389///         txn.commit();
390///     }
391/// }
392///
393/// enum RollBackOnDropStrategy {}
394/// impl DropManually<Transaction> for RollBackOnDropStrategy {
395///     fn drop_manually(txn: Transaction) {
396///         txn.roll_back();
397///     }
398/// }
399/// ```
400///
401/// ### `repr()` guarantee.
402///
403/// This type is guaranteed to be a mere `#[repr(transparent)]` wrapper around its `FieldTy`.
404///
405/// ### A silly, but interesting example: DIY-ing our own `ManuallyDrop<T>`
406///
407/// ```rust
408/// use ::safe_manually_drop::prelude::*;
409///
410/// pub
411/// enum ForgetOnDropStrategy {}
412///
413/// impl<T> DropManually<T> for ForgetOnDropStrategy {
414///     fn drop_manually(value: T) {
415///         ::core::mem::forget(value);
416///     }
417/// }
418///
419/// pub
420/// type ManuallyDrop<T> = SafeManuallyDrop<T, ForgetOnDropStrategy>;
421/// ```
422///
423///   - Note: do not do this in actual code, since calling `forget()` temporarily asserts validity
424///     of the `value`, which means the resulting type is completey unable to offer
425///     [`ManuallyDrop::take()`]-like APIs of any sort, and whatnot.
426#[repr(transparent)]
427pub
428struct SafeManuallyDrop<FieldTy, ContainingType = diagnostics::MissingSecondTypeParam>
429where
430    ContainingType : DropManually<FieldTy>,
431{
432    _phantom: PD<fn() -> ContainingType>,
433    field: ManuallyDrop<FieldTy>,
434}
435
436/// The impl tying everything together.
437///
438/// The main reason why an <code>impl [DropManually]</code> Just Works™, thanks to the following
439/// blanket `impl`:
440///
441/// <code>impl\<FieldTy\> Drop for SafeManuallyDrop\<FieldTy, …\> where … : DropManually\<FieldTy\> { </code>
442impl<FieldTy, ContainingType : DropManually<FieldTy>>
443    Drop
444for
445    SafeManuallyDrop<FieldTy, ContainingType>
446{
447    #[inline]
448    fn drop(&mut self) {
449        let owned: FieldTy = unsafe {
450            MD::take(&mut self.field)
451        };
452        ContainingType::drop_manually(owned)
453    }
454}
455
456impl<FieldTy, ContainingType : DropManually<FieldTy>> SafeManuallyDrop<FieldTy, ContainingType> {
457    /// Main, `const`-friendly, way to construct a [`SafeManuallyDrop<FieldTy, _>`] instance.
458    ///
459    /// Alternatively, there is a <code>[From]\<FieldTy> impl</code> as well.
460    ///
461    /// Tangentially, there shall also be <code>[Deref] \& [DerefMut] impls</code> with
462    /// `Target = FieldTy`.
463    ///
464    /// [Deref]: `::core::ops::Deref`
465    /// [DerefMut]: `::core::ops::DerefMut`
466    #[inline]
467    pub
468    const
469    fn new(value: FieldTy) -> Self {
470        #[allow(non_local_definitions)]
471        impl<FieldTy, ContainingType : DropManually<FieldTy>>
472            From<FieldTy>
473        for
474            SafeManuallyDrop<FieldTy, ContainingType>
475        {
476            fn from(field: FieldTy) -> Self {
477                Self::new(field)
478            }
479        }
480
481        Self {
482            _phantom: PD,
483            field: MD::new(value),
484        }
485    }
486
487    /// The inverse / reverse operation of the [`Self::new()`] constructor: _deconstructs_ a
488    /// [`SafeManuallyDrop<FieldTy, …>`][`SafeManuallyDrop`] back into a bare `FieldTy` type, which,
489    /// by virtue of this operation, shall go back to its default drop glue (rather than the
490    /// _overridden_ one of <code>impl [DropManually]\<FieldTy\> for … {</code>).
491    ///
492    /// Such a process is typically called _defusing_ the (extra or special) drop glue.
493    #[inline]
494    #[allow(nonstandard_style)]
495    pub
496    const
497    fn into_inner_defusing_impl_Drop(self) -> FieldTy {
498        union ConstUncheckedTransmuter<Src, Dst> {
499            src: MD<Src>,
500            dst: MD<Dst>,
501        }
502        unsafe {
503            // Safety: `repr(transparent)`, and no extra validity nor safety invariants at play.
504            MD::into_inner(
505                ConstUncheckedTransmuter::<
506                    SafeManuallyDrop<FieldTy, ContainingType>,
507                    FieldTy,
508                >
509                {
510                    src: MD::new(self),
511                }
512                .dst
513            )
514        }
515    }
516}
517
518impl<FieldTy, ContainingType : DropManually<FieldTy>>
519    ::core::ops::Deref
520for
521    SafeManuallyDrop<FieldTy, ContainingType>
522{
523    type Target = FieldTy;
524
525    #[inline]
526    fn deref(&self) -> &FieldTy {
527        &self.field
528    }
529}
530
531impl<FieldTy, ContainingType : DropManually<FieldTy>>
532    ::core::ops::DerefMut
533for
534    SafeManuallyDrop<FieldTy, ContainingType>
535{
536    #[inline]
537    fn deref_mut(&mut self) -> &mut FieldTy {
538        &mut self.field
539    }
540}
541
542/// Some helper for a nicer diagnostic suggestion/nudge in case of a forgotten second type
543/// parameter.
544mod diagnostics {
545    use super::*;
546
547    pub enum MissingSecondTypeParam {}
548
549    impl<FieldTy> DropManually<FieldTy> for MissingSecondTypeParam
550    where
551        for<'never_true> MissingSecondTypeParam : ExplicitlyProvided,
552    {
553        fn drop_manually(_: FieldTy) {
554            unreachable!()
555        }
556    }
557
558    #[diagnostic::on_unimplemented(
559        message = "\
560            missing second type parameter for `SafeManuallyDrop<FieldTy, …>`. \
561            Please use the containing `struct/enum` for it, such as: `Self`.\
562        ",
563        label = "help: use `SafeManuallyDrop<FieldTy, Self>` instead.",
564    )]
565    pub trait ExplicitlyProvided {}
566}
567
568#[doc = include_str!("compile_fail_tests.md")]
569mod _compile_fail_tests {}