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