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
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 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
68unsafe 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
81unsafe 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
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: OxPtrUninit) -> bool {
162 unsafe {
163 target.put(Weak::<T>::new());
164 }
165 true
166}
167
168unsafe 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
176unsafe 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 .variance(VarianceDesc {
220 base: Variance::Bivariant,
221 deps: &const { [VarianceDep::covariant(T::SHAPE)] },
222 })
223 .build()
224 };
225}
226
227unsafe 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
232unsafe 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
239static 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
293unsafe 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
298unsafe 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 .variance(VarianceDesc {
422 base: Variance::Bivariant,
423 deps: &const { [VarianceDep::covariant(T::SHAPE)] },
424 })
425 .build()
426 };
427}
428
429static 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 let arc_uninit_ptr = arc_shape.allocate().unwrap();
601
602 let new_into_fn = arc_def
604 .vtable
605 .new_into_fn
606 .expect("Arc<T> should have new_into_fn");
607
608 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 let borrow_fn = arc_def
620 .vtable
621 .borrow_fn
622 .expect("Arc<T> should have borrow_fn");
623
624 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
626 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
628
629 unsafe {
632 arc_shape
633 .call_drop_in_place(arc_ptr)
634 .expect("Arc<T> should have drop_in_place");
635 }
636
637 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 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 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
671 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
672 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
674
675 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
677 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
678 let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
681 .expect("Upgrade should succeed while original Arc exists");
682
683 let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
685 let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
687 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
689
690 unsafe {
692 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 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 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 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
733 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
734 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
736
737 unsafe {
739 arc_shape.call_drop_in_place(arc1_ptr).unwrap();
740 arc_shape.deallocate_mut(arc1_ptr).unwrap();
741 }
742
743 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
745 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
746 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
748
749 assert!(
751 upgrade_result.is_none(),
752 "Upgrade should fail after the strong Arc is dropped"
753 );
754
755 unsafe {
757 arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
759
760 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 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 let slice_builder_vtable = arc_slice_def
779 .vtable
780 .slice_builder_vtable
781 .expect("Arc<[i32]> should have slice_builder_vtable");
782
783 let builder_ptr = (slice_builder_vtable.new_fn)();
785
786 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 let convert_fn = slice_builder_vtable.convert_fn;
797 let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
798
799 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 let slice = unsafe { borrowed_ptr.get::<[i32]>() };
808 assert_eq!(slice, &[1, 2, 3, 4, 5]);
809
810 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 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 let slice_builder_vtable = arc_slice_def
829 .vtable
830 .slice_builder_vtable
831 .expect("Arc<[String]> should have slice_builder_vtable");
832
833 let builder_ptr = (slice_builder_vtable.new_fn)();
835
836 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 let free_fn = slice_builder_vtable.free_fn;
848 unsafe { free_fn(builder_ptr) };
849
850 }
852}