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 try_from: None,
372 try_into_inner: None,
373 try_borrow_inner: None,
374 partial_eq: None,
375 partial_cmp: None,
376 cmp: None,
377 };
378
379 ShapeBuilder::for_sized::<Self>("Weak")
380 .type_name(type_name_weak::<T>)
381 .vtable_indirect(&VTABLE)
382 .type_ops_indirect(
383 &const {
384 TypeOpsIndirect {
385 drop_in_place: weak_drop::<T>,
386 default_in_place: Some(weak_default::<T>),
387 clone_into: Some(weak_clone::<Weak<T>>),
388 is_truthy: None,
389 }
390 },
391 )
392 .ty(Type::User(UserType::Opaque))
393 .def(Def::Pointer(PointerDef {
394 vtable: &const {
395 PointerVTable {
396 upgrade_into_fn: Some(weak_upgrade_into::<T>),
397 ..PointerVTable::new()
398 }
399 },
400 pointee: Some(T::SHAPE),
401 weak: None,
402 strong: Some(<Arc<T> as Facet>::SHAPE),
403 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
404 known: Some(KnownPointer::ArcWeak),
405 }))
406 .type_params(&[crate::TypeParam {
407 name: "T",
408 shape: T::SHAPE,
409 }])
410 .inner(T::SHAPE)
411 .variance(Shape::computed_variance)
413 .build()
414 };
415}
416
417static WEAK_STR_TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
419 drop_in_place: weak_str_drop,
420 default_in_place: None,
421 clone_into: Some(weak_clone::<Weak<str>>),
422 is_truthy: None,
423};
424
425static WEAK_VTABLE: VTableIndirect = VTableIndirect {
426 display: None,
427 debug: Some(weak_debug),
428 hash: None,
429 invariants: None,
430 parse: None,
431 try_from: None,
432 try_into_inner: None,
433 try_borrow_inner: None,
434 partial_eq: None,
435 partial_cmp: None,
436 cmp: None,
437};
438
439unsafe impl<'a> Facet<'a> for Weak<str> {
440 const SHAPE: &'static crate::Shape = &const {
441 fn type_name_weak_str(
442 _shape: &'static crate::Shape,
443 f: &mut core::fmt::Formatter<'_>,
444 opts: TypeNameOpts,
445 ) -> core::fmt::Result {
446 write!(f, "Weak")?;
447 if let Some(opts) = opts.for_children() {
448 write!(f, "<")?;
449 str::SHAPE.write_type_name(f, opts)?;
450 write!(f, ">")?;
451 } else {
452 write!(f, "<…>")?;
453 }
454 Ok(())
455 }
456
457 ShapeBuilder::for_sized::<Self>("Weak")
458 .type_name(type_name_weak_str)
459 .vtable_indirect(&WEAK_VTABLE)
460 .type_ops_indirect(&WEAK_STR_TYPE_OPS)
461 .ty(Type::User(UserType::Opaque))
462 .def(Def::Pointer(PointerDef {
463 vtable: &const {
464 PointerVTable {
465 upgrade_into_fn: Some(|weak, strong| unsafe {
466 let upgraded = weak.as_const().get::<Weak<str>>().upgrade()?;
467 Some(strong.put(upgraded))
468 }),
469 ..PointerVTable::new()
470 }
471 },
472 pointee: Some(str::SHAPE),
473 weak: None,
474 strong: Some(<Arc<str> as Facet>::SHAPE),
475 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
476 known: Some(KnownPointer::ArcWeak),
477 }))
478 .type_params(&[crate::TypeParam {
479 name: "T",
480 shape: str::SHAPE,
481 }])
482 .build()
483 };
484}
485
486unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
487 const SHAPE: &'static crate::Shape = &const {
488 fn type_name_weak_slice<'a, U: Facet<'a>>(
489 _shape: &'static crate::Shape,
490 f: &mut core::fmt::Formatter<'_>,
491 opts: TypeNameOpts,
492 ) -> core::fmt::Result {
493 write!(f, "Weak")?;
494 if let Some(opts) = opts.for_children() {
495 write!(f, "<")?;
496 <[U]>::SHAPE.write_type_name(f, opts)?;
497 write!(f, ">")?;
498 } else {
499 write!(f, "<…>")?;
500 }
501 Ok(())
502 }
503
504 const VTABLE: VTableIndirect = VTableIndirect {
505 display: None,
506 debug: Some(weak_debug),
507 hash: None,
508 invariants: None,
509 parse: None,
510 try_from: None,
511 try_into_inner: None,
512 try_borrow_inner: None,
513 partial_eq: None,
514 partial_cmp: None,
515 cmp: None,
516 };
517
518 ShapeBuilder::for_sized::<Self>("Weak")
519 .type_name(type_name_weak_slice::<U>)
520 .vtable_indirect(&VTABLE)
521 .type_ops_indirect(
522 &const {
523 TypeOpsIndirect {
524 drop_in_place: weak_slice_drop::<U>,
525 default_in_place: None,
526 clone_into: Some(weak_clone::<Weak<[U]>>),
527 is_truthy: None,
528 }
529 },
530 )
531 .ty(Type::User(UserType::Opaque))
532 .def(Def::Pointer(PointerDef {
533 vtable: &const {
534 PointerVTable {
535 upgrade_into_fn: Some(|weak, strong| unsafe {
536 let upgraded = weak.as_const().get::<Weak<[U]>>().upgrade()?;
537 Some(strong.put(upgraded))
538 }),
539 ..PointerVTable::new()
540 }
541 },
542 pointee: Some(<[U]>::SHAPE),
543 weak: None,
544 strong: Some(<Arc<[U]> as Facet>::SHAPE),
545 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
546 known: Some(KnownPointer::ArcWeak),
547 }))
548 .type_params(&[crate::TypeParam {
549 name: "T",
550 shape: <[U]>::SHAPE,
551 }])
552 .build()
553 };
554}
555
556#[cfg(test)]
557mod tests {
558 use core::mem::ManuallyDrop;
559
560 use alloc::string::String;
561 use alloc::sync::{Arc, Weak as ArcWeak};
562
563 use super::*;
564
565 #[test]
566 fn test_arc_type_params() {
567 let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
568 panic!("Arc<T> should only have 1 type param")
569 };
570 assert_eq!(type_param_1.shape(), i32::SHAPE);
571 }
572
573 #[test]
574 fn test_arc_vtable_1_new_borrow_drop() {
575 facet_testhelpers::setup();
576
577 let arc_shape = <Arc<String>>::SHAPE;
578 let arc_def = arc_shape
579 .def
580 .into_pointer()
581 .expect("Arc<T> should have a smart pointer definition");
582
583 let arc_uninit_ptr = arc_shape.allocate().unwrap();
585
586 let new_into_fn = arc_def
588 .vtable
589 .new_into_fn
590 .expect("Arc<T> should have new_into_fn");
591
592 let mut value = ManuallyDrop::new(String::from("example"));
594 let arc_ptr = unsafe {
595 new_into_fn(
596 arc_uninit_ptr,
597 PtrMut::new(NonNull::from(&mut value).as_ptr()),
598 )
599 };
600 let borrow_fn = arc_def
604 .vtable
605 .borrow_fn
606 .expect("Arc<T> should have borrow_fn");
607
608 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
610 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
612
613 unsafe {
616 arc_shape
617 .call_drop_in_place(arc_ptr)
618 .expect("Arc<T> should have drop_in_place");
619 }
620
621 unsafe { arc_shape.deallocate_mut(arc_ptr).unwrap() };
624 }
625
626 #[test]
627 fn test_arc_vtable_2_downgrade_upgrade_drop() {
628 facet_testhelpers::setup();
629
630 let arc_shape = <Arc<String>>::SHAPE;
631 let arc_def = arc_shape
632 .def
633 .into_pointer()
634 .expect("Arc<T> should have a smart pointer definition");
635
636 let weak_shape = <ArcWeak<String>>::SHAPE;
637 let weak_def = weak_shape
638 .def
639 .into_pointer()
640 .expect("ArcWeak<T> should have a smart pointer definition");
641
642 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
644 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
645 let mut value = ManuallyDrop::new(String::from("example"));
646 let arc1_ptr = unsafe {
647 new_into_fn(
648 arc1_uninit_ptr,
649 PtrMut::new(NonNull::from(&mut value).as_ptr()),
650 )
651 };
652
653 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
655 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
656 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
658
659 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
661 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
662 let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
665 .expect("Upgrade should succeed while original Arc exists");
666
667 let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
669 let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
671 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
673
674 unsafe {
676 arc_shape.call_drop_in_place(arc1_ptr).unwrap();
678 arc_shape.deallocate_mut(arc1_ptr).unwrap();
679 arc_shape.call_drop_in_place(arc2_ptr).unwrap();
680 arc_shape.deallocate_mut(arc2_ptr).unwrap();
681
682 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
684 weak_shape.deallocate_mut(weak1_ptr).unwrap();
685 }
686 }
687
688 #[test]
689 fn test_arc_vtable_3_downgrade_drop_try_upgrade() {
690 facet_testhelpers::setup();
691
692 let arc_shape = <Arc<String>>::SHAPE;
693 let arc_def = arc_shape
694 .def
695 .into_pointer()
696 .expect("Arc<T> should have a smart pointer definition");
697
698 let weak_shape = <ArcWeak<String>>::SHAPE;
699 let weak_def = weak_shape
700 .def
701 .into_pointer()
702 .expect("ArcWeak<T> should have a smart pointer definition");
703
704 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
706 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
707 let mut value = ManuallyDrop::new(String::from("example"));
708 let arc1_ptr = unsafe {
709 new_into_fn(
710 arc1_uninit_ptr,
711 PtrMut::new(NonNull::from(&mut value).as_ptr()),
712 )
713 };
714
715 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
717 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
718 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
720
721 unsafe {
723 arc_shape.call_drop_in_place(arc1_ptr).unwrap();
724 arc_shape.deallocate_mut(arc1_ptr).unwrap();
725 }
726
727 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
729 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
730 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
732
733 assert!(
735 upgrade_result.is_none(),
736 "Upgrade should fail after the strong Arc is dropped"
737 );
738
739 unsafe {
741 arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
743
744 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
746 weak_shape.deallocate_mut(weak1_ptr).unwrap();
747 }
748 }
749
750 #[test]
751 fn test_arc_vtable_6_slice_builder() {
752 facet_testhelpers::setup();
753
754 let arc_slice_shape = <Arc<[i32]>>::SHAPE;
756 let arc_slice_def = arc_slice_shape
757 .def
758 .into_pointer()
759 .expect("Arc<[i32]> should have a smart pointer definition");
760
761 let slice_builder_vtable = arc_slice_def
763 .vtable
764 .slice_builder_vtable
765 .expect("Arc<[i32]> should have slice_builder_vtable");
766
767 let builder_ptr = (slice_builder_vtable.new_fn)();
769
770 let push_fn = slice_builder_vtable.push_fn;
772 let values = [1i32, 2, 3, 4, 5];
773 for &value in &values {
774 let mut value_copy = value;
775 let value_ptr = PtrMut::new(NonNull::from(&mut value_copy).as_ptr());
776 unsafe { push_fn(builder_ptr, value_ptr) };
777 }
778
779 let convert_fn = slice_builder_vtable.convert_fn;
781 let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
782
783 let borrow_fn = arc_slice_def
785 .vtable
786 .borrow_fn
787 .expect("Arc<[i32]> should have borrow_fn");
788 let borrowed_ptr = unsafe { borrow_fn(arc_slice_ptr) };
789
790 let slice = unsafe { borrowed_ptr.get::<[i32]>() };
792 assert_eq!(slice, &[1, 2, 3, 4, 5]);
793
794 unsafe {
796 let _ = Box::from_raw(arc_slice_ptr.as_ptr::<Arc<[i32]>>() as *mut Arc<[i32]>);
797 }
798 }
799
800 #[test]
801 fn test_arc_vtable_7_slice_builder_free() {
802 facet_testhelpers::setup();
803
804 let arc_slice_shape = <Arc<[String]>>::SHAPE;
806 let arc_slice_def = arc_slice_shape
807 .def
808 .into_pointer()
809 .expect("Arc<[String]> should have a smart pointer definition");
810
811 let slice_builder_vtable = arc_slice_def
813 .vtable
814 .slice_builder_vtable
815 .expect("Arc<[String]> should have slice_builder_vtable");
816
817 let builder_ptr = (slice_builder_vtable.new_fn)();
819
820 let push_fn = slice_builder_vtable.push_fn;
822 let strings = ["hello", "world", "test"];
823 for &s in &strings {
824 let mut value = ManuallyDrop::new(String::from(s));
825 let value_ptr = PtrMut::new(NonNull::from(&mut value).as_ptr());
826 unsafe { push_fn(builder_ptr, value_ptr) };
827 }
828
829 let free_fn = slice_builder_vtable.free_fn;
832 unsafe { free_fn(builder_ptr) };
833
834 }
836}