summaryrefslogtreecommitdiffstats
path: root/third_party/rust/pin-project/examples/pinned_drop-expanded.rs
blob: d96dd98e1253464f23bd01380b765b075282c347 (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
// Original code (./pinned_drop.rs):
//
// ```rust
// #![allow(dead_code)]
//
// use pin_project::{pin_project, pinned_drop};
// use std::pin::Pin;
//
// #[pin_project(PinnedDrop)]
// pub struct Foo<'a, T> {
//     was_dropped: &'a mut bool,
//     #[pin]
//     field: T,
// }
//
// #[pinned_drop]
// fn drop_foo<T>(mut this: Pin<&mut Foo<'_, T>>) {
//     **this.project().was_dropped = true;
// }
//
// fn main() {}
// ```

#![allow(dead_code, unused_imports, unused_parens)]

use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;

pub struct Foo<'a, T> {
    was_dropped: &'a mut bool,
    // #[pin]
    field: T,
}

#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
pub(crate) struct __FooProjection<'pin, 'a, T> {
    was_dropped: &'pin mut (&'a mut bool),
    field: ::core::pin::Pin<&'pin mut (T)>,
}

#[allow(dead_code)] // This lint warns unused fields/variants.
pub(crate) struct __FooProjectionRef<'pin, 'a, T> {
    was_dropped: &'pin (&'a mut bool),
    field: ::core::pin::Pin<&'pin (T)>,
}

impl<'a, T> Foo<'a, T> {
    pub(crate) fn project<'pin>(
        self: ::core::pin::Pin<&'pin mut Self>,
    ) -> __FooProjection<'pin, 'a, T> {
        unsafe {
            let Foo { was_dropped, field } = self.get_unchecked_mut();
            __FooProjection { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
        }
    }
    pub(crate) fn project_ref<'pin>(
        self: ::core::pin::Pin<&'pin Self>,
    ) -> __FooProjectionRef<'pin, 'a, T> {
        unsafe {
            let Foo { was_dropped, field } = self.get_ref();
            __FooProjectionRef { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
        }
    }
}

#[allow(single_use_lifetimes)]
impl<'a, T> ::core::ops::Drop for Foo<'a, T> {
    fn drop(&mut self) {
        // Safety - we're in 'drop', so we know that 'self' will
        // never move again.
        let pinned_self = unsafe { ::core::pin::Pin::new_unchecked(self) };
        // We call `pinned_drop` only once. Since `PinnedDrop::drop`
        // is an unsafe function 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);
        }
    }
}

// It is safe to implement PinnedDrop::drop, but it is not safe to call it.
// This is because destructors can be called multiple times (double dropping
// is unsound: rust-lang/rust#62360).
//
// Ideally, it would be desirable to be able to prohibit manual calls in the
// same way as Drop::drop, but the library cannot. 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]`.
// **Do not call or implement this trait directly.**
impl<T> ::pin_project::__private::PinnedDrop for Foo<'_, T> {
    // Since calling it twice on the same object would be UB,
    // this method is unsafe.
    unsafe fn drop(self: Pin<&mut Self>) {
        fn __drop_inner<T>(__self: Pin<&mut Foo<'_, T>>) {
            **__self.project().was_dropped = true;
        }
        __drop_inner(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.
#[allow(non_snake_case)]
fn __unpin_scope_Foo() {
    pub struct __Foo<'pin, 'a, T> {
        __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>,
        __field0: T,
        __lifetime0: &'a (),
    }
    impl<'pin, 'a, T> ::core::marker::Unpin for Foo<'a, T> where
        __Foo<'pin, 'a, T>: ::core::marker::Unpin
    {
    }
}

// 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.
#[allow(single_use_lifetimes)]
#[allow(non_snake_case)]
#[deny(safe_packed_borrows)]
fn __pin_project_assert_not_repr_packed_Foo<'a, T>(val: &Foo<'a, T>) {
    &val.was_dropped;
    &val.field;
}

fn main() {}