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