summaryrefslogtreecommitdiffstats
path: root/third_party/rust/pin-project/examples/pinned_drop-expanded.rs
blob: 82207b60b161b3a41dd2d80abb5c85a3ddd1f64d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Original code (./pinned_drop.rs):
//
// ```rust
// #![allow(dead_code)]
//
// use std::pin::Pin;
//
// use pin_project::{pin_project, pinned_drop};
//
// #[pin_project(PinnedDrop)]
// pub struct Struct<'a, T> {
//     was_dropped: &'a mut bool,
//     #[pin]
//     field: T,
// }
//
// #[pinned_drop]
// fn drop_Struct<T>(mut this: Pin<&mut Struct<'_, T>>) {
//     **this.project().was_dropped = true;
// }
//
// fn main() {}
// ```

#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)]
#![allow(clippy::needless_lifetimes, clippy::mut_mut)]

use std::pin::Pin;

use pin_project::{pin_project, pinned_drop};

// #[pin_project(PinnedDrop)]
pub struct Struct<'a, T> {
    was_dropped: &'a mut bool,
    // #[pin]
    field: T,
}

const _: () = {
    pub(crate) struct __StructProjection<'pin, 'a, T>
    where
        Struct<'a, T>: 'pin,
    {
        was_dropped: &'pin mut (&'a mut bool),
        field: ::pin_project::__private::Pin<&'pin mut (T)>,
    }
    pub(crate) struct __StructProjectionRef<'pin, 'a, T>
    where
        Struct<'a, T>: 'pin,
    {
        was_dropped: &'pin (&'a mut bool),
        field: ::pin_project::__private::Pin<&'pin (T)>,
    }

    impl<'a, T> Struct<'a, T> {
        pub(crate) fn project<'pin>(
            self: ::pin_project::__private::Pin<&'pin mut Self>,
        ) -> __StructProjection<'pin, 'a, T> {
            unsafe {
                let Self { was_dropped, field } = self.get_unchecked_mut();
                __StructProjection {
                    was_dropped,
                    field: ::pin_project::__private::Pin::new_unchecked(field),
                }
            }
        }
        pub(crate) fn project_ref<'pin>(
            self: ::pin_project::__private::Pin<&'pin Self>,
        ) -> __StructProjectionRef<'pin, 'a, T> {
            unsafe {
                let Self { was_dropped, field } = self.get_ref();
                __StructProjectionRef {
                    was_dropped,
                    field: ::pin_project::__private::Pin::new_unchecked(field),
                }
            }
        }
    }

    // Ensure that it's impossible to use pin projections on a #[repr(packed)]
    // struct.
    //
    // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
    // for details.
    #[forbid(unaligned_references, safe_packed_borrows)]
    fn __assert_not_repr_packed<'a, T>(this: &Struct<'a, T>) {
        let _ = &this.was_dropped;
        let _ = &this.field;
    }

    impl<'a, T> ::pin_project::__private::Drop for Struct<'a, T> {
        fn drop(&mut self) {
            // Safety - we're in 'drop', so we know that 'self' will
            // never move again.
            let pinned_self = unsafe { ::pin_project::__private::Pin::new_unchecked(self) };
            // We call `pinned_drop` only once. Since `PinnedDrop::drop`
            // is an unsafe method and a private API, it is never called again in safe
            // code *unless the user uses a maliciously crafted macro*.
            unsafe {
                ::pin_project::__private::PinnedDrop::drop(pinned_self);
            }
        }
    }

    // Automatically create the appropriate conditional `Unpin` implementation.
    //
    // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
    // for details.
    pub struct __Struct<'pin, 'a, T> {
        __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>,
        __field0: T,
        __lifetime0: &'a (),
    }
    impl<'pin, 'a, T> ::pin_project::__private::Unpin for Struct<'a, T> where
        __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
    {
    }
    // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
    #[doc(hidden)]
    unsafe impl<'pin, 'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> where
        __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
    {
    }
};

// Implementing `PinnedDrop::drop` is safe, but calling it is not safe.
// This is because destructors can be called multiple times in safe code and
// [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360).
//
// Ideally, it would be desirable to be able to forbid manual calls in
// the same way as `Drop::drop`, but the library cannot do it. So, by using
// macros and replacing them with private traits, we prevent users from
// calling `PinnedDrop::drop`.
//
// Users can implement [`Drop`] safely using `#[pinned_drop]` and can drop a
// type that implements `PinnedDrop` using the [`drop`] function safely.
// **Do not call or implement this trait directly.**
#[doc(hidden)]
impl<T> ::pin_project::__private::PinnedDrop for Struct<'_, T> {
    // Since calling it twice on the same object would be UB,
    // this method is unsafe.
    unsafe fn drop(self: Pin<&mut Self>) {
        #[allow(clippy::needless_pass_by_value)]
        fn __drop_inner<T>(__self: Pin<&mut Struct<'_, T>>) {
            // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`.
            fn __drop_inner() {}

            **__self.project().was_dropped = true;
        }
        __drop_inner(self);
    }
}

fn main() {}