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