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}