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