facet_core/impls_alloc/
arc.rs

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