1use std::mem::ManuallyDrop;
2use std::rc::Rc;
3use std::sync::Arc;
4
5use tycho_types::error::Error;
6use tycho_types::prelude::*;
7
8pub trait SafeDelete: 'static {
12 fn rc_into_safe_delete(self: Rc<Self>) -> Rc<dyn SafeDelete>;
13}
14
15impl<T: 'static> SafeDelete for T {
16 #[inline]
17 fn rc_into_safe_delete(self: Rc<Self>) -> Rc<dyn SafeDelete> {
18 self
19 }
20}
21
22#[repr(transparent)]
27pub struct SafeRc<T: SafeDelete + ?Sized>(pub(crate) ManuallyDrop<Rc<T>>);
28
29impl<T: SafeDelete> SafeRc<T> {
30 #[inline]
31 pub fn new(value: T) -> Self {
32 Self(ManuallyDrop::new(Rc::new(value)))
33 }
34
35 #[inline]
36 pub fn try_unwrap(this: Self) -> Result<T, Self> {
37 match Rc::try_unwrap(Self::into_inner(this)) {
38 Ok(value) => Ok(value),
39 Err(rc) => Err(Self(ManuallyDrop::new(rc))),
40 }
41 }
42}
43
44impl<T: SafeDelete + ?Sized> SafeRc<T> {
45 #[inline]
46 pub fn into_inner(mut this: Self) -> Rc<T> {
47 let value = unsafe { ManuallyDrop::take(&mut this.0) };
49 std::mem::forget(this);
51
52 value
53 }
54
55 #[inline]
56 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
57 Rc::get_mut(&mut *this.0)
58 }
59
60 #[inline]
61 pub fn ptr_eq(lhs: &Self, rhs: &Self) -> bool {
62 Rc::<T>::ptr_eq(&*lhs.0, &*rhs.0)
63 }
64
65 #[inline]
66 pub fn as_ptr(&self) -> *const T {
67 Rc::as_ptr(&*self.0)
68 }
69}
70
71impl<T: SafeDelete + Clone> SafeRc<T> {
72 #[inline]
73 pub fn unwrap_or_clone(this: Self) -> T {
74 Rc::unwrap_or_clone(Self::into_inner(this))
75 }
76}
77
78impl<T: Default + SafeDelete> Default for SafeRc<T> {
81 fn default() -> Self {
82 Self(ManuallyDrop::new(Rc::<T>::default()))
83 }
84}
85
86impl<T: SafeDelete + ?Sized> Clone for SafeRc<T> {
87 #[inline]
88 fn clone(&self) -> Self {
89 Self(self.0.clone())
90 }
91}
92
93impl<T: SafeDelete + std::fmt::Display + ?Sized> std::fmt::Display for SafeRc<T> {
94 #[inline]
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 std::fmt::Display::fmt(&*self.0, f)
97 }
98}
99
100impl<T: SafeDelete + std::fmt::Debug + ?Sized> std::fmt::Debug for SafeRc<T> {
101 #[inline]
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 std::fmt::Debug::fmt(&*self.0, f)
104 }
105}
106
107impl<T: Eq + SafeDelete + ?Sized> Eq for SafeRc<T> {}
108
109impl<T: PartialEq + SafeDelete + ?Sized> PartialEq for SafeRc<T> {
110 #[inline]
111 fn eq(&self, other: &Self) -> bool {
112 T::eq(&*self.0, &*other.0)
113 }
114}
115
116impl<T: Ord + SafeDelete + ?Sized> Ord for SafeRc<T> {
117 #[inline]
118 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
119 T::cmp(&*self.0, &*other.0)
120 }
121}
122
123impl<T: PartialOrd + SafeDelete + ?Sized> PartialOrd for SafeRc<T> {
124 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
125 T::partial_cmp(&*self.0, &*other.0)
126 }
127}
128
129impl<T: SafeDelete + ?Sized> Drop for SafeRc<T> {
130 fn drop(&mut self) {
131 let value = unsafe { ManuallyDrop::take(&mut self.0) };
133
134 if Rc::strong_count(&value) == 1 {
152 SafeDeleter::retire(value.rc_into_safe_delete());
153 }
154 }
155}
156
157impl<T: SafeDelete + ?Sized> std::ops::Deref for SafeRc<T> {
158 type Target = T;
159
160 #[inline]
161 fn deref(&self) -> &Self::Target {
162 &self.0
163 }
164}
165
166impl<T: SafeDelete + ?Sized> AsRef<T> for SafeRc<T> {
167 #[inline]
168 fn as_ref(&self) -> &T {
169 &self.0
170 }
171}
172
173impl<T: SafeDelete + ?Sized> From<Rc<T>> for SafeRc<T> {
174 #[inline]
175 fn from(value: Rc<T>) -> Self {
176 Self(ManuallyDrop::new(value))
177 }
178}
179
180impl<T: SafeDelete> From<T> for SafeRc<T> {
181 #[inline]
182 fn from(value: T) -> Self {
183 Self::new(value)
184 }
185}
186
187#[cfg(feature = "arbitrary")]
188impl<'a, T: SafeDelete + arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for SafeRc<T> {
189 #[inline]
190 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
191 u.arbitrary().map(Self::new)
192 }
193
194 #[inline]
195 fn size_hint(depth: usize) -> (usize, Option<usize>) {
196 Self::try_size_hint(depth).unwrap_or_default()
197 }
198
199 #[inline]
200 fn try_size_hint(
201 depth: usize,
202 ) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
203 <T as arbitrary::Arbitrary>::try_size_hint(depth)
204 }
205}
206
207pub trait SafeRcMakeMut: SafeDelete {
211 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self;
212}
213
214impl<T: SafeRcMakeMut + ?Sized> SafeRc<T> {
215 #[inline]
216 pub fn make_mut(&mut self) -> &mut T {
217 T::rc_make_mut(&mut *self.0)
218 }
219}
220
221impl SafeRcMakeMut for () {
222 #[inline]
223 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
224 Rc::make_mut(rc)
225 }
226}
227
228impl<T: Clone + 'static> SafeRcMakeMut for Box<T> {
229 #[inline]
230 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
231 Rc::make_mut(rc)
232 }
233}
234
235impl<T: ?Sized + 'static> SafeRcMakeMut for Rc<T> {
236 #[inline]
237 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
238 Rc::make_mut(rc)
239 }
240}
241
242impl<T: ?Sized + 'static> SafeRcMakeMut for Arc<T> {
243 #[inline]
244 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
245 Rc::make_mut(rc)
246 }
247}
248
249impl<T: Clone + 'static> SafeRcMakeMut for Vec<T> {
250 #[inline]
251 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
252 Rc::make_mut(rc)
253 }
254}
255
256impl SafeRcMakeMut for String {
257 #[inline]
258 fn rc_make_mut(rc: &mut Rc<Self>) -> &mut Self {
259 Rc::make_mut(rc)
260 }
261}
262
263impl<'a, T: Load<'a> + SafeDelete> Load<'a> for SafeRc<T> {
266 #[inline]
267 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
268 let value = ok!(Rc::<T>::load_from(slice));
269 Ok(Self(ManuallyDrop::new(value)))
270 }
271}
272
273impl<T: Store + SafeDelete + ?Sized> Store for SafeRc<T> {
274 #[inline]
275 fn store_into(&self, b: &mut CellBuilder, c: &dyn CellContext) -> Result<(), Error> {
276 T::store_into(&*self.0, b, c)
277 }
278}
279
280struct SafeDeleter {
283 to_delete: std::cell::RefCell<Vec<Rc<dyn SafeDelete>>>,
284 is_active: std::cell::Cell<bool>,
285}
286
287impl SafeDeleter {
288 fn retire(value: Rc<dyn SafeDelete>) {
289 thread_local! {
290 static DELETER: SafeDeleter = const {
291 SafeDeleter {
292 to_delete: std::cell::RefCell::new(Vec::new()),
293 is_active: std::cell::Cell::new(false),
294 }
295 };
296 }
297
298 let mut value = ManuallyDrop::new(value);
299
300 match DELETER.try_with(|deleter| {
301 let value = unsafe { ManuallyDrop::take(&mut value) };
304
305 if deleter.is_active.get() {
306 deleter.to_delete.borrow_mut().push(value);
308 return;
309 }
310
311 deleter.is_active.set(true);
313
314 drop(value);
317
318 loop {
320 let mut to_delete = deleter.to_delete.borrow_mut();
322 match to_delete.pop() {
323 Some(value) => {
324 drop(to_delete);
326 drop(value);
328 }
329 None => break,
330 }
331 }
332
333 deleter.is_active.set(false);
335 }) {
336 Ok(()) => {}
337 Err(_) => drop(unsafe { ManuallyDrop::take(&mut value) }),
341 }
342 }
343}
344
345#[cfg(test)]
346mod tests {
347 use super::*;
348
349 #[test]
350 #[cfg_attr(miri, ignore)]
351 fn drop_deep_tuple() {
352 let mut tuple = SafeRc::new_dyn_value(());
353 for _ in 0..1000000 {
354 tuple = SafeRc::new_dyn_value(vec![tuple]);
355 }
356 }
357}