facet_core/impls_alloc/
arc.rs

1use core::ptr::NonNull;
2
3use alloc::boxed::Box;
4use alloc::sync::{Arc, Weak};
5use alloc::vec::Vec;
6
7use crate::shape_util::vtable_builder_for_ptr;
8use crate::{
9    Def, Facet, KnownPointer, PointerDef, PointerFlags, PointerVTable, PtrConst, PtrMut, PtrUninit,
10    Shape, SliceBuilderVTable, TryBorrowInnerError, TryFromError, TryIntoInnerError, Type,
11    UserType, value_vtable,
12};
13
14unsafe impl<'a, T: Facet<'a>> Facet<'a> for Arc<T> {
15    const SHAPE: &'static crate::Shape = &const {
16        crate::Shape::builder_for_sized::<Self>()
17            .vtable({
18                // Define the functions for transparent conversion between Arc<T> and T
19                unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
20                    src_ptr: PtrConst<'src>,
21                    src_shape: &'static Shape,
22                    dst: PtrUninit<'dst>,
23                ) -> Result<PtrMut<'dst>, TryFromError> {
24                    if src_shape.id != T::SHAPE.id {
25                        return Err(TryFromError::UnsupportedSourceShape {
26                            src_shape,
27                            expected: &[T::SHAPE],
28                        });
29                    }
30                    let t = unsafe { src_ptr.read::<T>() };
31                    let arc = Arc::new(t);
32                    Ok(unsafe { dst.put(arc) })
33                }
34
35                unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
36                    src_ptr: PtrMut<'src>,
37                    dst: PtrUninit<'dst>,
38                ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
39                    use alloc::sync::Arc;
40
41                    // Read the Arc from the source pointer
42                    let arc = unsafe { src_ptr.read::<Arc<T>>() };
43
44                    // Try to unwrap the Arc to get exclusive ownership
45                    match Arc::try_unwrap(arc) {
46                        Ok(inner) => Ok(unsafe { dst.put(inner) }),
47                        Err(arc) => {
48                            // Arc is shared, so we can't extract the inner value
49                            core::mem::forget(arc);
50                            Err(TryIntoInnerError::Unavailable)
51                        }
52                    }
53                }
54
55                unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
56                    src_ptr: PtrConst<'src>,
57                ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
58                    let arc = unsafe { src_ptr.get::<Arc<T>>() };
59                    Ok(PtrConst::new(NonNull::from(&**arc)))
60                }
61
62                let mut vtable = vtable_builder_for_ptr::<T, Self>()
63                    .type_name(|f, opts| {
64                        write!(f, "{}", Self::SHAPE.type_identifier)?;
65                        if let Some(opts) = opts.for_children() {
66                            write!(f, "<")?;
67                            (T::SHAPE.vtable.type_name())(f, opts)?;
68                            write!(f, ">")?;
69                        } else {
70                            write!(f, "<…>")?;
71                        }
72                        Ok(())
73                    })
74                    .build();
75
76                {
77                    vtable.try_from = Some(try_from::<T>);
78                    vtable.try_into_inner = Some(try_into_inner::<T>);
79                    vtable.try_borrow_inner = Some(try_borrow_inner::<T>);
80                }
81                vtable
82            })
83            .type_identifier("Arc")
84            .type_params(&[crate::TypeParam {
85                name: "T",
86                shape: T::SHAPE,
87            }])
88            .ty(Type::User(UserType::Opaque))
89            .def(Def::Pointer(
90                PointerDef::builder()
91                    .pointee(T::SHAPE)
92                    .flags(PointerFlags::ATOMIC)
93                    .known(KnownPointer::Arc)
94                    .weak(|| <Weak<T> as Facet>::SHAPE)
95                    .vtable(
96                        &const {
97                            PointerVTable::builder()
98                                .borrow_fn(|this| {
99                                    let arc_ptr = unsafe { this.as_ptr::<Arc<T>>() };
100                                    let ptr = unsafe { &**arc_ptr };
101                                    PtrConst::new(NonNull::from(ptr))
102                                })
103                                .new_into_fn(|this, ptr| {
104                                    let t = unsafe { ptr.read::<T>() };
105                                    let arc = Arc::new(t);
106                                    unsafe { this.put(arc) }
107                                })
108                                .downgrade_into_fn(|strong, weak| unsafe {
109                                    weak.put(Arc::downgrade(strong.get::<Self>()))
110                                })
111                                .build()
112                        },
113                    )
114                    .build(),
115            ))
116            .inner(T::SHAPE)
117            .build()
118    };
119}
120
121unsafe impl<'a> Facet<'a> for Arc<str> {
122    const SHAPE: &'static crate::Shape = &const {
123        crate::Shape::builder_for_sized::<Self>()
124            .vtable({
125                vtable_builder_for_ptr::<str, Self>()
126                    .type_name(|f, opts| {
127                        write!(f, "{}", Self::SHAPE.type_identifier)?;
128                        if let Some(opts) = opts.for_children() {
129                            write!(f, "<")?;
130                            (str::SHAPE.vtable.type_name())(f, opts)?;
131                            write!(f, ">")?;
132                        } else {
133                            write!(f, "<…>")?;
134                        }
135                        Ok(())
136                    })
137                    .build()
138            })
139            .type_identifier("Arc")
140            .type_params(&[crate::TypeParam {
141                name: "T",
142                shape: str::SHAPE,
143            }])
144            .ty(Type::User(UserType::Opaque))
145            .def(Def::Pointer(
146                PointerDef::builder()
147                    .pointee(str::SHAPE)
148                    .flags(PointerFlags::ATOMIC)
149                    .known(KnownPointer::Arc)
150                    .weak(|| <Weak<str> as Facet>::SHAPE)
151                    .vtable(
152                        &const {
153                            PointerVTable::builder()
154                                .borrow_fn(|this| unsafe {
155                                    let concrete = this.get::<Arc<str>>();
156                                    let s: &str = concrete;
157                                    PtrConst::new(NonNull::from(s))
158                                })
159                                .downgrade_into_fn(|strong, weak| unsafe {
160                                    weak.put(Arc::downgrade(strong.get::<Self>()))
161                                })
162                                .build()
163                        },
164                    )
165                    .build(),
166            ))
167            .inner(str::SHAPE)
168            .build()
169    };
170}
171
172unsafe impl<'a, U: Facet<'a>> Facet<'a> for Arc<[U]> {
173    const SHAPE: &'static crate::Shape = &const {
174        fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut<'static> {
175            let v = Box::new(Vec::<U>::new());
176            let raw = Box::into_raw(v);
177            PtrMut::new(unsafe { NonNull::new_unchecked(raw) })
178        }
179
180        fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
181            unsafe {
182                let vec = builder.as_mut::<Vec<U>>();
183                let value = item.read::<U>();
184                vec.push(value);
185            }
186        }
187
188        fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut<'static>) -> PtrConst<'static> {
189            unsafe {
190                let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
191                let arc: Arc<[U]> = (*vec_box).into();
192                let arc_box = Box::new(arc);
193                PtrConst::new(NonNull::new_unchecked(Box::into_raw(arc_box)))
194            }
195        }
196
197        fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut<'static>) {
198            unsafe {
199                let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
200            }
201        }
202
203        crate::Shape::builder_for_sized::<Self>()
204            .vtable({
205                vtable_builder_for_ptr::<[U], Self>()
206                    .type_name(|f, opts| {
207                        write!(f, "{}", Self::SHAPE.type_identifier)?;
208                        if let Some(opts) = opts.for_children() {
209                            write!(f, "<")?;
210                            (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
211                            write!(f, ">")?;
212                        } else {
213                            write!(f, "<…>")?;
214                        }
215                        Ok(())
216                    })
217                    .build()
218            })
219            .type_identifier("Arc")
220            .type_params(&[crate::TypeParam {
221                name: "T",
222                shape: <[U]>::SHAPE,
223            }])
224            .ty(Type::User(UserType::Opaque))
225            .def(Def::Pointer(
226                PointerDef::builder()
227                    .pointee(<[U]>::SHAPE)
228                    .flags(PointerFlags::ATOMIC)
229                    .known(KnownPointer::Arc)
230                    .weak(|| <Weak<[U]> as Facet>::SHAPE)
231                    .vtable(
232                        &const {
233                            PointerVTable::builder()
234                                .borrow_fn(|this| unsafe {
235                                    let concrete = this.get::<Arc<[U]>>();
236                                    let s: &[U] = concrete;
237                                    PtrConst::new(NonNull::from(s))
238                                })
239                                .downgrade_into_fn(|strong, weak| unsafe {
240                                    weak.put(Arc::downgrade(strong.get::<Self>()))
241                                })
242                                .slice_builder_vtable(
243                                    &const {
244                                        SliceBuilderVTable::builder()
245                                            .new_fn(slice_builder_new::<U>)
246                                            .push_fn(slice_builder_push::<U>)
247                                            .convert_fn(slice_builder_convert::<U>)
248                                            .free_fn(slice_builder_free::<U>)
249                                            .build()
250                                    },
251                                )
252                                .build()
253                        },
254                    )
255                    .build(),
256            ))
257            .inner(<[U]>::SHAPE)
258            .build()
259    };
260}
261
262unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
263    const SHAPE: &'static crate::Shape = &const {
264        crate::Shape::builder_for_sized::<Self>()
265            .vtable({
266                value_vtable!(alloc::sync::Weak<T>, |f, opts| {
267                    write!(f, "{}", Self::SHAPE.type_identifier)?;
268                    if let Some(opts) = opts.for_children() {
269                        write!(f, "<")?;
270                        (T::SHAPE.vtable.type_name())(f, opts)?;
271                        write!(f, ">")?;
272                    } else {
273                        write!(f, "<…>")?;
274                    }
275                    Ok(())
276                })
277            })
278            .type_identifier("Weak")
279            .type_params(&[crate::TypeParam {
280                name: "T",
281                shape: T::SHAPE,
282            }])
283            .ty(Type::User(UserType::Opaque))
284            .def(Def::Pointer(
285                PointerDef::builder()
286                    .pointee(T::SHAPE)
287                    .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
288                    .known(KnownPointer::ArcWeak)
289                    .strong(<Arc<T> as Facet>::SHAPE)
290                    .vtable(
291                        &const {
292                            PointerVTable::builder()
293                                .upgrade_into_fn(|weak, strong| unsafe {
294                                    Some(strong.put(weak.get::<Self>().upgrade()?))
295                                })
296                                .build()
297                        },
298                    )
299                    .build(),
300            ))
301            .inner(T::SHAPE)
302            .build()
303    };
304}
305
306unsafe impl<'a> Facet<'a> for Weak<str> {
307    const SHAPE: &'static crate::Shape = &const {
308        crate::Shape::builder_for_sized::<Self>()
309            .vtable({
310                value_vtable!(alloc::sync::Weak<str>, |f, opts| {
311                    write!(f, "{}", Self::SHAPE.type_identifier)?;
312                    if let Some(opts) = opts.for_children() {
313                        write!(f, "<")?;
314                        (str::SHAPE.vtable.type_name())(f, opts)?;
315                        write!(f, ">")?;
316                    } else {
317                        write!(f, "<…>")?;
318                    }
319                    Ok(())
320                })
321            })
322            .type_identifier("Weak")
323            .type_params(&[crate::TypeParam {
324                name: "T",
325                shape: str::SHAPE,
326            }])
327            .ty(Type::User(UserType::Opaque))
328            .def(Def::Pointer(
329                PointerDef::builder()
330                    .pointee(str::SHAPE)
331                    .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
332                    .known(KnownPointer::ArcWeak)
333                    .strong(<Arc<str> as Facet>::SHAPE)
334                    .vtable(
335                        &const {
336                            PointerVTable::builder()
337                                .upgrade_into_fn(|weak, strong| unsafe {
338                                    Some(strong.put(weak.get::<Self>().upgrade()?))
339                                })
340                                .build()
341                        },
342                    )
343                    .build(),
344            ))
345            .inner(str::SHAPE)
346            .build()
347    };
348}
349
350unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
351    const SHAPE: &'static crate::Shape = &const {
352        crate::Shape::builder_for_sized::<Self>()
353            .vtable({
354                value_vtable!(alloc::sync::Weak<[U]>, |f, opts| {
355                    write!(f, "{}", Self::SHAPE.type_identifier)?;
356                    if let Some(opts) = opts.for_children() {
357                        write!(f, "<")?;
358                        (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
359                        write!(f, ">")?;
360                    } else {
361                        write!(f, "<…>")?;
362                    }
363                    Ok(())
364                })
365            })
366            .type_identifier("Weak")
367            .type_params(&[crate::TypeParam {
368                name: "T",
369                shape: <[U]>::SHAPE,
370            }])
371            .ty(Type::User(UserType::Opaque))
372            .def(Def::Pointer(
373                PointerDef::builder()
374                    .pointee(<[U]>::SHAPE)
375                    .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
376                    .known(KnownPointer::ArcWeak)
377                    .strong(<Arc<[U]> as Facet>::SHAPE)
378                    .vtable(
379                        &const {
380                            PointerVTable::builder()
381                                .upgrade_into_fn(|weak, strong| unsafe {
382                                    Some(strong.put(weak.get::<Self>().upgrade()?))
383                                })
384                                .build()
385                        },
386                    )
387                    .build(),
388            ))
389            .inner(<[U]>::SHAPE)
390            .build()
391    };
392}
393
394#[cfg(test)]
395mod tests {
396    use core::mem::ManuallyDrop;
397
398    use alloc::string::String;
399    use alloc::sync::{Arc, Weak as ArcWeak};
400
401    use super::*;
402
403    #[test]
404    fn test_arc_type_params() {
405        let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
406            panic!("Arc<T> should only have 1 type param")
407        };
408        assert_eq!(type_param_1.shape(), i32::SHAPE);
409    }
410
411    #[test]
412    fn test_arc_vtable_1_new_borrow_drop() {
413        facet_testhelpers::setup();
414
415        let arc_shape = <Arc<String>>::SHAPE;
416        let arc_def = arc_shape
417            .def
418            .into_pointer()
419            .expect("Arc<T> should have a smart pointer definition");
420
421        // Allocate memory for the Arc
422        let arc_uninit_ptr = arc_shape.allocate().unwrap();
423
424        // Get the function pointer for creating a new Arc from a value
425        let new_into_fn = arc_def
426            .vtable
427            .new_into_fn
428            .expect("Arc<T> should have new_into_fn");
429
430        // Create the value and initialize the Arc
431        let mut value = ManuallyDrop::new(String::from("example"));
432        let arc_ptr =
433            unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
434        // The value now belongs to the Arc, prevent its drop
435
436        // Get the function pointer for borrowing the inner value
437        let borrow_fn = arc_def
438            .vtable
439            .borrow_fn
440            .expect("Arc<T> should have borrow_fn");
441
442        // Borrow the inner value and check it
443        let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
444        // SAFETY: borrowed_ptr points to a valid String within the Arc
445        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
446
447        // Get the function pointer for dropping the Arc
448        let drop_fn = arc_shape
449            .vtable
450            .drop_in_place
451            .expect("Arc<T> should have drop_in_place");
452
453        // Drop the Arc in place
454        // SAFETY: arc_ptr points to a valid Arc<String>
455        unsafe { drop_fn(arc_ptr) };
456
457        // Deallocate the memory
458        // SAFETY: arc_ptr was allocated by arc_shape and is now dropped (but memory is still valid)
459        unsafe { arc_shape.deallocate_mut(arc_ptr).unwrap() };
460    }
461
462    #[test]
463    fn test_arc_vtable_2_downgrade_upgrade_drop() {
464        facet_testhelpers::setup();
465
466        let arc_shape = <Arc<String>>::SHAPE;
467        let arc_def = arc_shape
468            .def
469            .into_pointer()
470            .expect("Arc<T> should have a smart pointer definition");
471
472        let weak_shape = <ArcWeak<String>>::SHAPE;
473        let weak_def = weak_shape
474            .def
475            .into_pointer()
476            .expect("ArcWeak<T> should have a smart pointer definition");
477
478        // 1. Create the first Arc (arc1)
479        let arc1_uninit_ptr = arc_shape.allocate().unwrap();
480        let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
481        let mut value = ManuallyDrop::new(String::from("example"));
482        let arc1_ptr =
483            unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
484
485        // 2. Downgrade arc1 to create a weak pointer (weak1)
486        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
487        let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
488        // SAFETY: arc1_ptr points to a valid Arc, weak1_uninit_ptr is allocated for a Weak
489        let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
490
491        // 3. Upgrade weak1 to create a second Arc (arc2)
492        let arc2_uninit_ptr = arc_shape.allocate().unwrap();
493        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
494        // SAFETY: weak1_ptr points to a valid Weak, arc2_uninit_ptr is allocated for an Arc.
495        // Upgrade should succeed as arc1 still exists.
496        let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
497            .expect("Upgrade should succeed while original Arc exists");
498
499        // Check the content of the upgraded Arc
500        let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
501        // SAFETY: arc2_ptr points to a valid Arc<String>
502        let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
503        // SAFETY: borrowed_ptr points to a valid String
504        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
505
506        // 4. Drop everything and free memory
507        let arc_drop_fn = arc_shape.vtable.drop_in_place.unwrap();
508        let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
509
510        unsafe {
511            // Drop Arcs
512            arc_drop_fn(arc1_ptr);
513            arc_shape.deallocate_mut(arc1_ptr).unwrap();
514            arc_drop_fn(arc2_ptr);
515            arc_shape.deallocate_mut(arc2_ptr).unwrap();
516
517            // Drop Weak
518            weak_drop_fn(weak1_ptr);
519            weak_shape.deallocate_mut(weak1_ptr).unwrap();
520        }
521    }
522
523    #[test]
524    fn test_arc_vtable_3_downgrade_drop_try_upgrade() {
525        facet_testhelpers::setup();
526
527        let arc_shape = <Arc<String>>::SHAPE;
528        let arc_def = arc_shape
529            .def
530            .into_pointer()
531            .expect("Arc<T> should have a smart pointer definition");
532
533        let weak_shape = <ArcWeak<String>>::SHAPE;
534        let weak_def = weak_shape
535            .def
536            .into_pointer()
537            .expect("ArcWeak<T> should have a smart pointer definition");
538
539        // 1. Create the strong Arc (arc1)
540        let arc1_uninit_ptr = arc_shape.allocate().unwrap();
541        let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
542        let mut value = ManuallyDrop::new(String::from("example"));
543        let arc1_ptr =
544            unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
545
546        // 2. Downgrade arc1 to create a weak pointer (weak1)
547        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
548        let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
549        // SAFETY: arc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
550        let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
551
552        // 3. Drop and free the strong pointer (arc1)
553        let arc_drop_fn = arc_shape.vtable.drop_in_place.unwrap();
554        unsafe {
555            arc_drop_fn(arc1_ptr);
556            arc_shape.deallocate_mut(arc1_ptr).unwrap();
557        }
558
559        // 4. Attempt to upgrade the weak pointer (weak1)
560        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
561        let arc2_uninit_ptr = arc_shape.allocate().unwrap();
562        // SAFETY: weak1_ptr is valid (though points to dropped data), arc2_uninit_ptr is allocated for Arc
563        let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
564
565        // Assert that the upgrade failed
566        assert!(
567            upgrade_result.is_none(),
568            "Upgrade should fail after the strong Arc is dropped"
569        );
570
571        // 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
572        let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
573        unsafe {
574            // Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
575            arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
576
577            // Drop and deallocate the weak pointer
578            weak_drop_fn(weak1_ptr);
579            weak_shape.deallocate_mut(weak1_ptr).unwrap();
580        }
581    }
582
583    #[test]
584    fn test_arc_vtable_4_try_from() {
585        facet_testhelpers::setup();
586
587        // Get the shapes we'll be working with
588        let string_shape = <String>::SHAPE;
589        let arc_shape = <Arc<String>>::SHAPE;
590        let arc_def = arc_shape
591            .def
592            .into_pointer()
593            .expect("Arc<T> should have a smart pointer definition");
594
595        // 1. Create a String value
596        let value = ManuallyDrop::new(String::from("try_from test"));
597        let value_ptr = PtrConst::new(NonNull::from(&value));
598
599        // 2. Allocate memory for the Arc<String>
600        let arc_uninit_ptr = arc_shape.allocate().unwrap();
601
602        // 3. Get the try_from function from the Arc<String> shape's ValueVTable
603        let try_from_fn = arc_shape
604            .vtable
605            .try_from
606            .expect("Arc<T> should have try_from");
607
608        // 4. Try to convert String to Arc<String>
609        let arc_ptr = unsafe { try_from_fn(value_ptr, string_shape, arc_uninit_ptr) }
610            .expect("try_from should succeed");
611
612        // 5. Borrow the inner value and verify it's correct
613        let borrow_fn = arc_def
614            .vtable
615            .borrow_fn
616            .expect("Arc<T> should have borrow_fn");
617        let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
618
619        // SAFETY: borrowed_ptr points to a valid String within the Arc
620        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "try_from test");
621
622        // 6. Clean up
623        let drop_fn = arc_shape
624            .vtable
625            .drop_in_place
626            .expect("Arc<T> should have drop_in_place");
627
628        unsafe {
629            drop_fn(arc_ptr);
630            arc_shape.deallocate_mut(arc_ptr).unwrap();
631        }
632    }
633
634    #[test]
635    fn test_arc_vtable_5_try_into_inner() {
636        facet_testhelpers::setup();
637
638        // Get the shapes we'll be working with
639        let string_shape = <String>::SHAPE;
640        let arc_shape = <Arc<String>>::SHAPE;
641        let arc_def = arc_shape
642            .def
643            .into_pointer()
644            .expect("Arc<T> should have a smart pointer definition");
645
646        // 1. Create an Arc<String>
647        let arc_uninit_ptr = arc_shape.allocate().unwrap();
648        let new_into_fn = arc_def
649            .vtable
650            .new_into_fn
651            .expect("Arc<T> should have new_into_fn");
652
653        let mut value = ManuallyDrop::new(String::from("try_into_inner test"));
654        let arc_ptr =
655            unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
656
657        // 2. Allocate memory for the extracted String
658        let string_uninit_ptr = string_shape.allocate().unwrap();
659
660        // 3. Get the try_into_inner function from the Arc<String>'s ValueVTable
661        let try_into_inner_fn = arc_shape
662            .vtable
663            .try_into_inner
664            .expect("Arc<T> Shape should have try_into_inner");
665
666        // 4. Try to extract the String from the Arc<String>
667        // This should succeed because we have exclusive access to the Arc (strong count = 1)
668        let string_ptr = unsafe { try_into_inner_fn(arc_ptr, string_uninit_ptr) }
669            .expect("try_into_inner should succeed with exclusive access");
670
671        // 5. Verify the extracted String
672        assert_eq!(
673            unsafe { string_ptr.as_const().get::<String>() },
674            "try_into_inner test"
675        );
676
677        // 6. Clean up
678        let string_drop_fn = string_shape
679            .vtable
680            .drop_in_place
681            .expect("String should have drop_in_place");
682
683        unsafe {
684            // The Arc should already be dropped by try_into_inner
685            // But we still need to deallocate its memory
686            arc_shape.deallocate_mut(arc_ptr).unwrap();
687
688            // Drop and deallocate the extracted String
689            string_drop_fn(string_ptr);
690            string_shape.deallocate_mut(string_ptr).unwrap();
691        }
692    }
693
694    #[test]
695    fn test_arc_vtable_6_slice_builder() {
696        facet_testhelpers::setup();
697
698        // Get the shapes we'll be working with
699        let arc_slice_shape = <Arc<[i32]>>::SHAPE;
700        let arc_slice_def = arc_slice_shape
701            .def
702            .into_pointer()
703            .expect("Arc<[i32]> should have a smart pointer definition");
704
705        // Get the slice builder vtable
706        let slice_builder_vtable = arc_slice_def
707            .vtable
708            .slice_builder_vtable
709            .expect("Arc<[i32]> should have slice_builder_vtable");
710
711        // 1. Create a new builder
712        let builder_ptr = (slice_builder_vtable.new_fn)();
713
714        // 2. Push some items to the builder
715        let push_fn = slice_builder_vtable.push_fn;
716        let values = [1i32, 2, 3, 4, 5];
717        for &value in &values {
718            let mut value_copy = value;
719            let value_ptr = PtrMut::new(NonNull::from(&mut value_copy));
720            unsafe { push_fn(builder_ptr, value_ptr) };
721        }
722
723        // 3. Convert the builder to Arc<[i32]>
724        let convert_fn = slice_builder_vtable.convert_fn;
725        let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
726
727        // 4. Verify the contents by borrowing
728        let borrow_fn = arc_slice_def
729            .vtable
730            .borrow_fn
731            .expect("Arc<[i32]> should have borrow_fn");
732        let borrowed_ptr = unsafe { borrow_fn(arc_slice_ptr) };
733
734        // Convert the wide pointer to a slice reference
735        let slice = unsafe { borrowed_ptr.get::<[i32]>() };
736        assert_eq!(slice, &[1, 2, 3, 4, 5]);
737
738        // 5. Clean up - the Arc<[i32]> was boxed by convert_fn, we need to deallocate the Box
739        unsafe {
740            let _ = Box::from_raw(arc_slice_ptr.as_ptr::<Arc<[i32]>>() as *mut Arc<[i32]>);
741        }
742    }
743
744    #[test]
745    fn test_arc_vtable_7_slice_builder_free() {
746        facet_testhelpers::setup();
747
748        // Get the shapes we'll be working with
749        let arc_slice_shape = <Arc<[String]>>::SHAPE;
750        let arc_slice_def = arc_slice_shape
751            .def
752            .into_pointer()
753            .expect("Arc<[String]> should have a smart pointer definition");
754
755        // Get the slice builder vtable
756        let slice_builder_vtable = arc_slice_def
757            .vtable
758            .slice_builder_vtable
759            .expect("Arc<[String]> should have slice_builder_vtable");
760
761        // 1. Create a new builder
762        let builder_ptr = (slice_builder_vtable.new_fn)();
763
764        // 2. Push some items to the builder
765        let push_fn = slice_builder_vtable.push_fn;
766        let strings = ["hello", "world", "test"];
767        for &s in &strings {
768            let mut value = ManuallyDrop::new(String::from(s));
769            let value_ptr = PtrMut::new(NonNull::from(&mut value));
770            unsafe { push_fn(builder_ptr, value_ptr) };
771        }
772
773        // 3. Instead of converting, test the free function
774        // This simulates abandoning the builder without creating the Arc
775        let free_fn = slice_builder_vtable.free_fn;
776        unsafe { free_fn(builder_ptr) };
777
778        // If we get here without panicking, the free worked correctly
779    }
780}