Skip to main content

rust_spec/
drop.rs

1//! Drop behavior classification.
2//!
3//! Drop behavior specifies whether dropping a type runs custom drop cod3, automatic drop glue, or neither.
4//!
5//! In particular, if a type is [`CustomDrop<NoDrop>>`], it is guaranteed that no inner field of the type
6//! will run any drop glue. This can be used inside a custom drop implementation to safely take the value
7//! out of a mutable reference in a generic context without a risk of a double free.
8use core::{convert::Infallible, ops::Add};
9
10#[sealed::sealed]
11pub trait DropKind {
12    /// Drop glue required by a container that owns a field of this kind.
13    /// A field's custom destructor is automatic drop glue for its container.
14    type NeedsDrop: DropKind;
15}
16
17pub(crate) type NeedsDrop<T> = <T as DropKind>::NeedsDrop;
18
19/// Dropping this type does not run drop glue.
20pub enum NoDrop {}
21
22/// Owned contents need automatic drop glue.
23pub enum AutoDrop {}
24
25/// The type has a custom [`Drop`] implementation, with the given drop behavior for its contents.
26pub struct CustomDrop<I: DropKind>(core::marker::PhantomData<I>, Infallible);
27
28#[sealed::sealed]
29impl DropKind for NoDrop {
30    type NeedsDrop = NoDrop;
31}
32#[sealed::sealed]
33impl DropKind for AutoDrop {
34    type NeedsDrop = AutoDrop;
35}
36#[sealed::sealed]
37impl<K: DropKind> DropKind for CustomDrop<K> {
38    type NeedsDrop = AutoDrop;
39}
40
41impl<I: DropKind> Add<I> for NoDrop {
42    type Output = I::NeedsDrop;
43
44    fn add(self, _: I) -> Self::Output {
45        unreachable!()
46    }
47}
48
49impl<Rhs> Add<Rhs> for AutoDrop {
50    type Output = Self;
51
52    fn add(self, _: Rhs) -> Self::Output {
53        unreachable!()
54    }
55}
56
57impl Add<NoDrop> for CustomDrop<NoDrop> {
58    type Output = AutoDrop;
59
60    fn add(self, _: NoDrop) -> Self::Output {
61        unreachable!()
62    }
63}
64
65impl Add<AutoDrop> for CustomDrop<NoDrop> {
66    type Output = AutoDrop;
67
68    fn add(self, _: AutoDrop) -> Self::Output {
69        unreachable!()
70    }
71}
72
73impl<I: DropKind> Add<CustomDrop<I>> for CustomDrop<NoDrop> {
74    type Output = AutoDrop;
75
76    fn add(self, _: CustomDrop<I>) -> Self::Output {
77        unreachable!()
78    }
79}
80
81impl<Rhs> Add<Rhs> for CustomDrop<AutoDrop> {
82    type Output = AutoDrop;
83
84    fn add(self, _: Rhs) -> Self::Output {
85        unreachable!()
86    }
87}