facet_core/impls/alloc/
arc.rs

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