Skip to main content

structural/field/ownership/
on_drop.rs

1use super::{DropFields, MovedOutFields, PrePostDropFields};
2
3use std_::mem::ManuallyDrop;
4
5/////////////////////////////////////////////////////////////////////////////////
6
7/// Helper type for moving fields out of a Structural type.
8///
9/// # Drop behavior
10///
11/// The wrapped value is put inside a `ManuallyDrop` so that its destructor doesn't run.
12///
13/// When this is dropped,instead of running the destructor for the wrapped value,
14/// this calls [`DropFields::drop_fields`] on it,
15/// to drop the fields that haven't been moved out.
16///
17/// [`DropFields::drop_fields`]: ./trait.DropFields.html#tymethod.drop_fields
18///
19/// # Example
20///
21/// For an example that uses `IntoFieldsWrapper` there's the
22/// [implementation example] for [`RevIntoMultiFieldImpl`]
23///
24/// [implementation example]:
25/// ../multi_fields/trait.RevIntoMultiFieldImpl.html#implementation-example
26///
27/// [`RevIntoMultiFieldImpl`]: ../multi_fields/trait.RevIntoMultiFieldImpl.html
28///
29pub struct IntoFieldsWrapper<T: DropFields> {
30    value: ManuallyDrop<T>,
31    moved: MovedOutFields,
32}
33
34impl<T: DropFields> IntoFieldsWrapper<T> {
35    /// Constructs this `IntoFieldsWrapper`,wrapping the `value`.
36    ///
37    /// Also calls `DropFields::pre_move` on the wrapped value
38    ///
39    #[inline(always)]
40    pub fn new(mut value: T) -> Self {
41        DropFields::pre_move(&mut value);
42        Self {
43            value: ManuallyDrop::new(value),
44            moved: MovedOutFields::new(),
45        }
46    }
47
48    /// Gets mutable references to the wrapped value,
49    /// and the `MovedOutFields` that tracks which fields were moved out of it.
50    ///
51    /// # Safety
52    ///
53    /// The returned references must not be mutated,
54    /// only passed to accessor trait (declared in structural) methods for moving out fields .
55    ///
56    /// Mutating `MovedOutFields` incorrectly can lead to leaks and double dropped fields.
57    #[inline(always)]
58    pub unsafe fn inner_and_moved_mut(&mut self) -> (&mut T, &mut MovedOutFields) {
59        (&mut self.value, &mut self.moved)
60    }
61
62    /// Gets mutable pointers to the wrapped value,
63    /// and the `MovedOutFields` that tracks which fields were moved out of it.
64    ///
65    /// # Safety
66    ///
67    /// The returned pointers must not be mutated,
68    /// only passed to accessor trait (declared in structural) methods for moving out fields .
69    ///
70    /// Mutating `MovedOutFields` incorrectly can lead to leaks and double dropped fields.
71    #[inline(always)]
72    pub unsafe fn inner_and_moved_raw(&mut self) -> (*mut T, *mut MovedOutFields) {
73        (&mut *self.value as *mut T, &mut self.moved as *mut _)
74    }
75}
76
77impl<T: DropFields> Drop for IntoFieldsWrapper<T> {
78    #[inline(always)]
79    fn drop(&mut self) {
80        unsafe {
81            DropFields::drop_fields(&mut *self.value, self.moved);
82        }
83    }
84}
85
86/////////////////////////////////////////////////////////////////////////////////
87
88macro_rules! declare_run_on_drop {
89    (
90        $(#[$meta:meta])*
91        struct $struct:ident
92        $(where[$($where_preds:tt)*])?
93        $(#[$new_meta:meta])*
94        $(unsafe $(#$dummy:ident#)?)? fn new($($extra_var:ident : $extra_ty:ty),* $(,)?)
95        this=$this:ident,
96        fn drop(){$($drop:tt)*}
97    ) => (
98        $(#[$meta])*
99        pub struct $struct<'a,T>
100        $(where $($where_preds)*)?
101        {
102            mutref:&'a mut T,
103            $($extra_var : $extra_ty,)*
104        }
105
106        impl<'a,T> $struct<'a,T>
107        $(where $($where_preds)*)?
108        {
109            $(#[$new_meta])*
110            /// # Drop order
111            ///
112            /// Remember that variables on the stack are dropped in the opposite order
113            /// than they are declared.
114            ///
115            /// In this example:
116            /// ```ignore
117            /// let a=Foo;
118            /// let b=Bar;
119            /// let c=Baz;
120            /// ```
121            /// `c` gets dropped first,then `b`, then `a`.
122            #[inline(always)]
123            pub $(unsafe $(#$dummy#)?)?
124            fn new(mutref:&'a mut T $(,$extra_var : $extra_ty)*)->Self{
125                Self{
126                    mutref,
127                    $($extra_var,)*
128                }
129            }
130
131            /// Reborrows the wrapped mutable reference.
132            ///
133            /// # Safety
134            ///
135            /// The returned references must not be mutated,
136            /// only passed to accessor trait (declared in structural) methods for moving out fields .
137            #[inline(always)]
138            pub unsafe fn get_mut(&mut self)->&mut T{
139                self.mutref
140            }
141        }
142
143        impl<'a,T> Drop for  $struct<'a,T>
144        $(where $($where_preds)*)?
145        {
146            #[inline(always)]
147            fn drop(&mut self){
148                let $this=self;
149                $($drop)*
150            }
151        }
152
153    )
154}
155
156declare_run_on_drop! {
157    /// A guard that drops the value that a mutable reference points when *it* is dropped.
158    struct RunDrop
159
160    /// Constructs this RunDrop.
161    ///
162    /// # Safety
163    ///
164    /// In the destructor for this type,
165    /// this drops the value that the mutable reference points to.
166    ///
167    /// Once the destructor for this type runs,the pointed-to value must not be used again,
168    /// that includes the destructor for the value running.
169    unsafe fn new()
170
171    this=this,
172    fn drop(){
173        unsafe{
174            std_::ptr::drop_in_place(this.mutref)
175        }
176    }
177}
178
179declare_run_on_drop! {
180    /// A guard that calls [`PrePostDropFields::post_drop`] on the mutable reference
181    /// when *it* is dropped.
182    ///
183    /// [`PrePostDropFields::post_drop`]: ./trait.PrePostDropFields.html#tymethod.post_drop
184    struct RunPostDrop
185    where[ T: PrePostDropFields ]
186
187    /// Constructs this RunPostDrop.
188    ///
189    /// # Safety
190    ///
191    /// This has the same safety requirements as [`PrePostDropFields::post_drop`].
192    ///
193    /// [`PrePostDropFields::post_drop`]: ./trait.PrePostDropFields.html#tymethod.post_drop
194    unsafe fn new()
195
196    this=this,
197    fn drop(){
198        unsafe{
199            PrePostDropFields::post_drop(this.mutref)
200        }
201    }
202}
203
204declare_run_on_drop! {
205    /// A guard that calls [`DropFields::drop_fields`] on the mutable reference
206    /// when *it* is dropped.
207    ///
208    /// [`DropFields::drop_fields`]: ./trait.DropFields.html#tymethod.drop_fields
209    struct RunDropFields
210    where[ T: DropFields ]
211
212    /// Constructs this RunDropFields.
213    ///
214    /// # Safety
215    ///
216    /// This has the same safety requirements as [`DropFields::drop_fields`].
217    ///
218    /// [`DropFields::drop_fields`]: ./trait.DropFields.html#tymethod.drop_fields
219    unsafe fn new(moved: MovedOutFields)
220
221    this=this,
222    fn drop(){
223        unsafe{
224            this.mutref.drop_fields(this.moved)
225        }
226    }
227}
228
229impl<'a, T> RunDropFields<'a, T>
230where
231    T: DropFields,
232{
233    /// Gets mutable references to the wrapped value,
234    /// and the `MovedOutFields` that tracks which fields were moved out of it
235    ///
236    /// # Safety
237    ///
238    /// The returned references must not be mutated,
239    /// only passed to accessor trait (declared in structural) methods for moving out fields .
240    ///
241    /// Mutating `MovedOutFields` incorrectly can lead to leaks and double dropped fields.
242    pub unsafe fn get_mut_and_moved_fields(&mut self) -> (&mut T, &mut MovedOutFields) {
243        (&mut self.mutref, &mut self.moved)
244    }
245}