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 {}