1use std::{
62 mem::ManuallyDrop,
63 ops::{Deref, DerefMut},
64 rc::Rc,
65 sync::Arc,
66};
67
68pub trait Recursive {
71 type Container;
72
73 fn destruct(self) -> impl Iterator<Item = Self::Container>;
74}
75
76pub trait IntoOptionInner {
78 type Inner;
79
80 fn into_option_inner(self) -> Option<Self::Inner>;
86}
87
88#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
99#[repr(transparent)]
100pub struct FlatDrop<K>(ManuallyDrop<K>)
101where
102 K: IntoOptionInner,
103 K::Inner: Recursive<Container = K>;
104
105impl<K> Drop for FlatDrop<K>
106where
107 K: IntoOptionInner,
108 K::Inner: Recursive<Container = K>,
109{
110 fn drop(&mut self) {
111 let value = unsafe { ManuallyDrop::take(&mut self.0) };
114
115 let mut to_drop = vec![value];
117
118 while let Some(container) = to_drop.pop() {
121 if let Some(value) = container.into_option_inner() {
122 to_drop.extend(value.destruct());
123 }
124 }
125
126 }
128}
129
130impl<T> IntoOptionInner for Box<T> {
133 type Inner = T;
134
135 fn into_option_inner(self) -> Option<Self::Inner> {
136 Some(*self)
137 }
138}
139
140impl<T> IntoOptionInner for Rc<T> {
141 type Inner = T;
142
143 fn into_option_inner(self) -> Option<Self::Inner> {
144 Rc::into_inner(self)
145 }
146}
147
148impl<T> IntoOptionInner for Arc<T> {
149 type Inner = T;
150
151 fn into_option_inner(self) -> Option<Self::Inner> {
152 Arc::into_inner(self)
153 }
154}
155
156impl<K> FlatDrop<K>
157where
158 K: IntoOptionInner,
159 K::Inner: Recursive<Container = K>,
160{
161 pub const fn new(container: K) -> Self {
162 Self(ManuallyDrop::new(container))
163 }
164
165 pub fn into_inner(mut self) -> K {
166 let value = unsafe { ManuallyDrop::take(&mut self.0) };
169 std::mem::forget(self);
171 value
172 }
173}
174
175impl<K, T> AsRef<T> for FlatDrop<K>
176where
177 T: ?Sized,
178 K: IntoOptionInner,
179 K::Inner: Recursive<Container = K>,
180 K: AsRef<T>,
181{
182 fn as_ref(&self) -> &T {
183 (**self).as_ref()
184 }
185}
186
187impl<K, T> AsMut<T> for FlatDrop<K>
188where
189 T: ?Sized,
190 K: IntoOptionInner,
191 K::Inner: Recursive<Container = K>,
192 K: AsMut<T>,
193{
194 fn as_mut(&mut self) -> &mut T {
195 (**self).as_mut()
196 }
197}
198
199impl<K> Deref for FlatDrop<K>
200where
201 K: IntoOptionInner,
202 K::Inner: Recursive<Container = K>,
203{
204 type Target = K;
205
206 fn deref(&self) -> &K {
207 self.0.deref()
208 }
209}
210
211impl<K> DerefMut for FlatDrop<K>
212where
213 K: IntoOptionInner,
214 K::Inner: Recursive<Container = K>,
215{
216 fn deref_mut(&mut self) -> &mut K {
217 self.0.deref_mut()
218 }
219}
220
221impl<K> From<K> for FlatDrop<K>
222where
223 K: IntoOptionInner,
224 K::Inner: Recursive<Container = K>,
225{
226 fn from(value: K) -> Self {
227 Self::new(value)
228 }
229}
230
231impl<T> FlatDrop<Box<T>>
232where
233 T: Recursive<Container = Box<T>>,
234{
235 pub fn new_boxed(value: T) -> Self {
236 Self::new(Box::new(value))
237 }
238}
239
240impl<T> FlatDrop<Rc<T>>
241where
242 T: Recursive<Container = Rc<T>>,
243{
244 pub fn new_rc(value: T) -> Self {
245 Self::new(Rc::new(value))
246 }
247}
248
249impl<T> FlatDrop<Arc<T>>
250where
251 T: Recursive<Container = Arc<T>>,
252{
253 pub fn new_arc(value: T) -> Self {
254 Self::new(Arc::new(value))
255 }
256}
257
258#[cfg(feature = "serde")]
259impl<K> serde::Serialize for FlatDrop<K>
260where
261 K: IntoOptionInner,
262 K::Inner: Recursive<Container = K>,
263 K: serde::Serialize,
264{
265 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
266 where
267 S: serde::Serializer,
268 {
269 <K as serde::Serialize>::serialize(self, serializer)
270 }
271}
272
273#[cfg(feature = "serde")]
274impl<'de, K> serde::Deserialize<'de> for FlatDrop<K>
275where
276 K: IntoOptionInner,
277 K::Inner: Recursive<Container = K>,
278 K: serde::Deserialize<'de>,
279{
280 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
281 where
282 D: serde::Deserializer<'de>,
283 {
284 <K as serde::Deserialize>::deserialize(deserializer).map(Self::new)
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use crate::{FlatDrop, Recursive};
291
292 enum Natural {
294 Zero,
295 Succ(FlatDrop<Box<Natural>>),
296 }
297
298 impl Recursive for Natural {
299 type Container = Box<Natural>;
300
301 fn destruct(self) -> impl Iterator<Item = Self::Container> {
302 match self {
303 Natural::Zero => None,
304 Natural::Succ(pred) => Some(pred.into_inner()),
305 }
306 .into_iter()
307 }
308 }
309
310 impl Natural {
311 pub fn from_usize(value: usize) -> Self {
312 (0..value).fold(Self::Zero, |nat, _| {
313 Self::Succ(FlatDrop::new(Box::new(nat)))
314 })
315 }
316 }
317
318 #[test]
319 fn test_large_natural() {
320 const STACK_SIZE: usize = 4 * 1024;
322
323 fn task() {
324 let nat = Natural::from_usize(STACK_SIZE * 100);
325 println!("Dropping...");
326 drop(std::hint::black_box(nat));
327 println!("Dropped.");
328 }
329
330 std::thread::Builder::new()
331 .stack_size(STACK_SIZE)
332 .spawn(task)
333 .unwrap()
334 .join()
335 .unwrap();
336 }
337}