Skip to main content

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