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/// Dropping this type does not run drop glue.
11pub enum NoDrop {}
12
13/// Owned contents need automatic drop glue.
14pub enum AutoDrop {}
15
16/// The type has a custom [`Drop`] implementation, with the given drop behavior for its contents.
17pub struct CustomDrop<I: DropKind>(core::marker::PhantomData<I>, Infallible);
18
19#[sealed::sealed]
20pub trait DropKind {}
21
22#[sealed::sealed]
23impl DropKind for NoDrop {}
24#[sealed::sealed]
25impl DropKind for AutoDrop {}
26#[sealed::sealed]
27impl DropKind for CustomDrop<NoDrop> {}
28#[sealed::sealed]
29impl DropKind for CustomDrop<AutoDrop> {}
30
31impl Add<Self> for NoDrop {
32    type Output = Self;
33
34    fn add(self, _: Self) -> Self::Output {
35        unreachable!()
36    }
37}
38
39impl Add<AutoDrop> for NoDrop {
40    type Output = AutoDrop;
41
42    fn add(self, _: AutoDrop) -> Self::Output {
43        unreachable!()
44    }
45}
46
47impl<I: DropKind> Add<CustomDrop<I>> for NoDrop {
48    type Output = AutoDrop;
49
50    fn add(self, _: CustomDrop<I>) -> Self::Output {
51        unreachable!()
52    }
53}
54
55impl<Rhs> Add<Rhs> for AutoDrop {
56    type Output = Self;
57
58    fn add(self, _: Rhs) -> Self::Output {
59        unreachable!()
60    }
61}
62
63impl Add<NoDrop> for CustomDrop<NoDrop> {
64    type Output = AutoDrop;
65
66    fn add(self, _: NoDrop) -> Self::Output {
67        unreachable!()
68    }
69}
70
71impl Add<AutoDrop> for CustomDrop<NoDrop> {
72    type Output = AutoDrop;
73
74    fn add(self, _: AutoDrop) -> Self::Output {
75        unreachable!()
76    }
77}
78
79impl<I: DropKind> Add<CustomDrop<I>> for CustomDrop<NoDrop> {
80    type Output = AutoDrop;
81
82    fn add(self, _: CustomDrop<I>) -> Self::Output {
83        unreachable!()
84    }
85}
86
87impl<Rhs> Add<Rhs> for CustomDrop<AutoDrop> {
88    type Output = AutoDrop;
89
90    fn add(self, _: Rhs) -> Self::Output {
91        unreachable!()
92    }
93}