1use core::ptr::NonNull;
2
3use alloc::boxed::Box;
4use alloc::rc::{Rc, Weak};
5use alloc::vec::Vec;
6
7use crate::{
8 Def, Facet, KnownPointer, OxPtrConst, OxPtrMut, PointerDef, PointerFlags, PointerVTable,
9 PtrConst, PtrMut, PtrUninit, Shape, ShapeBuilder, SliceBuilderVTable, Type, TypeNameOpts,
10 TypeOpsIndirect, UserType, VTableIndirect,
11};
12
13fn rc_type_name<'a, T: Facet<'a>>(
19 _shape: &'static Shape,
20 f: &mut core::fmt::Formatter<'_>,
21 opts: TypeNameOpts,
22) -> core::fmt::Result {
23 write!(f, "Rc")?;
24 if let Some(opts) = opts.for_children() {
25 write!(f, "<")?;
26 T::SHAPE.write_type_name(f, opts)?;
27 write!(f, ">")?;
28 } else {
29 write!(f, "<…>")?;
30 }
31 Ok(())
32}
33
34unsafe fn rc_drop<T>(ox: OxPtrMut) {
36 unsafe {
37 core::ptr::drop_in_place(ox.ptr().as_ptr::<Rc<T>>() as *mut Rc<T>);
38 }
39}
40
41unsafe fn rc_debug<'a, T: Facet<'a>>(
43 ox: OxPtrConst,
44 f: &mut core::fmt::Formatter<'_>,
45) -> Option<core::fmt::Result> {
46 let rc = unsafe { ox.get::<Rc<T>>() };
47
48 let inner_ptr = PtrConst::new(NonNull::from(&**rc).as_ptr());
50 if let Some(result) = unsafe { T::SHAPE.call_debug(inner_ptr, f) } {
51 return Some(result);
52 }
53
54 Some(write!(f, "Rc(...)"))
56}
57
58unsafe fn rc_borrow_fn<T>(this: PtrConst) -> PtrConst {
60 let ptr = unsafe { Rc::<T>::as_ptr(this.get()) };
61 PtrConst::new(ptr)
62}
63
64unsafe fn rc_new_into_fn<'a, 'ptr, T: Facet<'a>>(this: PtrUninit, ptr: PtrMut) -> PtrMut {
66 let t = unsafe { ptr.read::<T>() };
67 let rc = Rc::new(t);
68 unsafe { this.put(rc) }
69}
70
71unsafe fn rc_downgrade_into_fn<'a, 'ptr, T: Facet<'a>>(strong: PtrMut, weak: PtrUninit) -> PtrMut {
73 unsafe { weak.put(Rc::downgrade(strong.get::<Rc<T>>())) }
74}
75
76unsafe impl<'a, T: Facet<'a>> Facet<'a> for Rc<T> {
77 const SHAPE: &'static Shape = &const {
78 ShapeBuilder::for_sized::<Rc<T>>("Rc")
79 .type_name(rc_type_name::<T>)
80 .ty(Type::User(UserType::Opaque))
81 .def(Def::Pointer(PointerDef {
82 vtable: &const {
83 PointerVTable {
84 borrow_fn: Some(rc_borrow_fn::<T>),
85 new_into_fn: Some(rc_new_into_fn::<T>),
86 downgrade_into_fn: Some(|strong, weak| unsafe {
87 rc_downgrade_into_fn::<T>(strong, weak)
88 }),
89 ..PointerVTable::new()
90 }
91 },
92 pointee: Some(T::SHAPE),
93 weak: Some(|| <Weak<T> as Facet>::SHAPE),
94 strong: None,
95 flags: PointerFlags::EMPTY,
96 known: Some(KnownPointer::Rc),
97 }))
98 .type_params(&[crate::TypeParam {
99 name: "T",
100 shape: T::SHAPE,
101 }])
102 .inner(T::SHAPE)
103 .variance(Shape::computed_variance)
105 .vtable_indirect(
106 &const {
107 VTableIndirect {
108 debug: Some(rc_debug::<T>),
109 display: None,
110 hash: None,
111 invariants: None,
112 parse: None,
113 parse_bytes: None,
114 try_from: None,
115 try_into_inner: None,
116 try_borrow_inner: None,
117 partial_eq: None,
118 partial_cmp: None,
119 cmp: None,
120 }
121 },
122 )
123 .type_ops_indirect(
124 &const {
125 TypeOpsIndirect {
126 drop_in_place: rc_drop::<T>,
127 default_in_place: None,
128 clone_into: None,
129 is_truthy: None,
130 }
131 },
132 )
133 .build()
134 };
135}
136
137fn rc_str_type_name(
143 _shape: &'static Shape,
144 f: &mut core::fmt::Formatter<'_>,
145 opts: TypeNameOpts,
146) -> core::fmt::Result {
147 write!(f, "Rc")?;
148 if let Some(opts) = opts.for_children() {
149 write!(f, "<")?;
150 str::SHAPE.write_type_name(f, opts)?;
151 write!(f, ">")?;
152 } else {
153 write!(f, "<…>")?;
154 }
155 Ok(())
156}
157
158unsafe fn rc_str_drop(ox: OxPtrMut) {
160 unsafe {
161 core::ptr::drop_in_place(ox.ptr().as_ptr::<Rc<str>>() as *mut Rc<str>);
162 }
163}
164
165unsafe fn rc_str_clone(src: OxPtrConst, dst: OxPtrMut) {
167 unsafe {
168 let value = src.get::<Rc<str>>().clone();
169 (dst.ptr().as_ptr::<Rc<str>>() as *mut Rc<str>).write(value);
170 }
171}
172
173unsafe fn rc_str_debug(
175 ox: OxPtrConst,
176 f: &mut core::fmt::Formatter<'_>,
177) -> Option<core::fmt::Result> {
178 let rc = unsafe { ox.get::<Rc<str>>() };
179 let s: &str = rc;
180 Some(write!(f, "Rc({s:?})"))
181}
182
183unsafe fn rc_str_borrow_fn(this: PtrConst) -> PtrConst {
185 unsafe {
186 let concrete = this.get::<Rc<str>>();
187 let s: &str = concrete;
188 PtrConst::new(NonNull::from(s).as_ptr())
189 }
190}
191
192unsafe fn rc_str_downgrade_into_fn(strong: PtrMut, weak: PtrUninit) -> PtrMut {
194 unsafe { weak.put(Rc::downgrade(strong.get::<Rc<str>>())) }
195}
196
197unsafe impl<'a> Facet<'a> for Rc<str> {
198 const SHAPE: &'static Shape = &const {
199 const VTABLE: VTableIndirect = VTableIndirect {
200 debug: Some(rc_str_debug),
201 display: None,
202 hash: None,
203 invariants: None,
204 parse: None,
205 parse_bytes: None,
206 try_from: None,
207 try_into_inner: None,
208 try_borrow_inner: None,
209 partial_eq: None,
210 partial_cmp: None,
211 cmp: None,
212 };
213
214 const TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
215 drop_in_place: rc_str_drop,
216 default_in_place: None,
217 clone_into: Some(rc_str_clone),
218 is_truthy: None,
219 };
220
221 ShapeBuilder::for_sized::<Rc<str>>("Rc")
222 .type_name(rc_str_type_name)
223 .ty(Type::User(UserType::Opaque))
224 .def(Def::Pointer(PointerDef {
225 vtable: &const {
226 PointerVTable {
227 borrow_fn: Some(rc_str_borrow_fn),
228 downgrade_into_fn: Some(|strong, weak| unsafe {
229 rc_str_downgrade_into_fn(strong, weak)
230 }),
231 ..PointerVTable::new()
232 }
233 },
234 pointee: Some(str::SHAPE),
235 weak: Some(|| <Weak<str> as Facet>::SHAPE),
236 strong: None,
237 flags: PointerFlags::EMPTY,
238 known: Some(KnownPointer::Rc),
239 }))
240 .type_params(&[crate::TypeParam {
241 name: "T",
242 shape: str::SHAPE,
243 }])
244 .vtable_indirect(&VTABLE)
245 .type_ops_indirect(&TYPE_OPS)
246 .build()
247 };
248}
249
250fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut {
255 let v = Box::new(Vec::<U>::new());
256 let raw = Box::into_raw(v);
257 PtrMut::new(unsafe { NonNull::new_unchecked(raw as *mut u8) }.as_ptr())
258}
259
260fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
261 unsafe {
262 let vec = builder.as_mut::<Vec<U>>();
263 let value = item.read::<U>();
264 vec.push(value);
265 }
266}
267
268fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut) -> PtrConst {
269 unsafe {
270 let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
271 let rc: Rc<[U]> = (*vec_box).into();
272 let rc_box = Box::new(rc);
273 PtrConst::new(NonNull::new_unchecked(Box::into_raw(rc_box) as *mut u8).as_ptr())
274 }
275}
276
277fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut) {
278 unsafe {
279 let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
280 }
281}
282
283fn rc_slice_type_name<'a, U: Facet<'a>>(
285 _shape: &'static Shape,
286 f: &mut core::fmt::Formatter<'_>,
287 opts: TypeNameOpts,
288) -> core::fmt::Result {
289 write!(f, "Rc")?;
290 if let Some(opts) = opts.for_children() {
291 write!(f, "<")?;
292 <[U]>::SHAPE.write_type_name(f, opts)?;
293 write!(f, ">")?;
294 } else {
295 write!(f, "<…>")?;
296 }
297 Ok(())
298}
299
300unsafe fn rc_slice_drop<U>(ox: OxPtrMut) {
302 unsafe {
303 core::ptr::drop_in_place(ox.ptr().as_ptr::<Rc<[U]>>() as *mut Rc<[U]>);
304 }
305}
306
307unsafe fn rc_slice_debug<'a, U: Facet<'a>>(
309 ox: OxPtrConst,
310 f: &mut core::fmt::Formatter<'_>,
311) -> Option<core::fmt::Result> {
312 let rc = unsafe { ox.get::<Rc<[U]>>() };
313 let slice: &[U] = rc;
314
315 let slice_ptr = PtrConst::new(NonNull::from(slice).as_ptr());
317 if let Some(result) = unsafe { <[U]>::SHAPE.call_debug(slice_ptr, f) } {
318 return Some(result);
319 }
320
321 Some(write!(f, "Rc([...])"))
322}
323
324unsafe fn rc_slice_borrow_fn<U>(this: PtrConst) -> PtrConst {
326 unsafe {
327 let concrete = this.get::<Rc<[U]>>();
328 let s: &[U] = concrete;
329 PtrConst::new(NonNull::from(s).as_ptr())
330 }
331}
332
333unsafe fn rc_slice_downgrade_into_fn<'a, 'ptr, U: Facet<'a>>(
335 strong: PtrMut,
336 weak: PtrUninit,
337) -> PtrMut {
338 unsafe { weak.put(Rc::downgrade(strong.get::<Rc<[U]>>())) }
339}
340
341unsafe impl<'a, U: Facet<'a>> Facet<'a> for Rc<[U]> {
342 const SHAPE: &'static Shape = &const {
343 ShapeBuilder::for_sized::<Rc<[U]>>("Rc")
344 .type_name(rc_slice_type_name::<U>)
345 .ty(Type::User(UserType::Opaque))
346 .def(Def::Pointer(PointerDef {
347 vtable: &const {
348 PointerVTable {
349 borrow_fn: Some(rc_slice_borrow_fn::<U>),
350 downgrade_into_fn: Some(|strong, weak| unsafe {
351 rc_slice_downgrade_into_fn::<U>(strong, weak)
352 }),
353 slice_builder_vtable: Some(
354 &const {
355 SliceBuilderVTable::new(
356 slice_builder_new::<U>,
357 slice_builder_push::<U>,
358 slice_builder_convert::<U>,
359 slice_builder_free::<U>,
360 )
361 },
362 ),
363 ..PointerVTable::new()
364 }
365 },
366 pointee: Some(<[U]>::SHAPE),
367 weak: Some(|| <Weak<[U]> as Facet>::SHAPE),
368 strong: None,
369 flags: PointerFlags::EMPTY,
370 known: Some(KnownPointer::Rc),
371 }))
372 .type_params(&[crate::TypeParam {
373 name: "T",
374 shape: <[U]>::SHAPE,
375 }])
376 .vtable_indirect(
377 &const {
378 VTableIndirect {
379 debug: Some(rc_slice_debug::<U>),
380 display: None,
381 hash: None,
382 invariants: None,
383 parse: None,
384 parse_bytes: None,
385 try_from: None,
386 try_into_inner: None,
387 try_borrow_inner: None,
388 partial_eq: None,
389 partial_cmp: None,
390 cmp: None,
391 }
392 },
393 )
394 .type_ops_indirect(
395 &const {
396 TypeOpsIndirect {
397 drop_in_place: rc_slice_drop::<U>,
398 default_in_place: None,
399 clone_into: None,
400 is_truthy: None,
401 }
402 },
403 )
404 .build()
405 };
406}
407
408fn weak_type_name<'a, T: Facet<'a>>(
414 _shape: &'static Shape,
415 f: &mut core::fmt::Formatter<'_>,
416 opts: TypeNameOpts,
417) -> core::fmt::Result {
418 write!(f, "Weak")?;
419 if let Some(opts) = opts.for_children() {
420 write!(f, "<")?;
421 T::SHAPE.write_type_name(f, opts)?;
422 write!(f, ">")?;
423 } else {
424 write!(f, "<…>")?;
425 }
426 Ok(())
427}
428
429unsafe fn weak_drop<T>(ox: OxPtrMut) {
431 unsafe {
432 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>);
433 }
434}
435
436unsafe fn weak_default<T>(ox: OxPtrMut) {
438 unsafe {
439 (ox.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(Weak::<T>::new());
440 }
441}
442
443unsafe fn weak_clone<T>(src: OxPtrConst, dst: OxPtrMut) {
445 unsafe {
446 let value = src.get::<Weak<T>>().clone();
447 (dst.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(value);
448 }
449}
450
451unsafe fn weak_debug(
453 _ox: OxPtrConst,
454 f: &mut core::fmt::Formatter<'_>,
455) -> Option<core::fmt::Result> {
456 Some(write!(f, "(Weak)"))
457}
458
459unsafe fn weak_upgrade_into_fn<'a, 'ptr, T: Facet<'a>>(
461 weak: PtrMut,
462 strong: PtrUninit,
463) -> Option<PtrMut> {
464 unsafe { Some(strong.put(weak.get::<Weak<T>>().upgrade()?)) }
465}
466
467unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
468 const SHAPE: &'static Shape = &const {
469 ShapeBuilder::for_sized::<Weak<T>>("Weak")
470 .type_name(weak_type_name::<T>)
471 .ty(Type::User(UserType::Opaque))
472 .def(Def::Pointer(PointerDef {
473 vtable: &const {
474 PointerVTable {
475 upgrade_into_fn: Some(|weak, strong| unsafe {
476 weak_upgrade_into_fn::<T>(weak, strong)
477 }),
478 ..PointerVTable::new()
479 }
480 },
481 pointee: Some(T::SHAPE),
482 weak: None,
483 strong: Some(<Rc<T> as Facet>::SHAPE),
484 flags: PointerFlags::WEAK,
485 known: Some(KnownPointer::RcWeak),
486 }))
487 .type_params(&[crate::TypeParam {
488 name: "T",
489 shape: T::SHAPE,
490 }])
491 .inner(T::SHAPE)
492 .variance(Shape::computed_variance)
494 .vtable_indirect(
495 &const {
496 VTableIndirect {
497 debug: Some(weak_debug),
498 display: None,
499 hash: None,
500 invariants: None,
501 parse: None,
502 parse_bytes: None,
503 try_from: None,
504 try_into_inner: None,
505 try_borrow_inner: None,
506 partial_eq: None,
507 partial_cmp: None,
508 cmp: None,
509 }
510 },
511 )
512 .type_ops_indirect(
513 &const {
514 TypeOpsIndirect {
515 drop_in_place: weak_drop::<T>,
516 default_in_place: Some(weak_default::<T>),
517 clone_into: Some(weak_clone::<T>),
518 is_truthy: None,
519 }
520 },
521 )
522 .build()
523 };
524}
525
526fn weak_str_type_name(
532 _shape: &'static Shape,
533 f: &mut core::fmt::Formatter<'_>,
534 opts: TypeNameOpts,
535) -> core::fmt::Result {
536 write!(f, "Weak")?;
537 if let Some(opts) = opts.for_children() {
538 write!(f, "<")?;
539 str::SHAPE.write_type_name(f, opts)?;
540 write!(f, ">")?;
541 } else {
542 write!(f, "<…>")?;
543 }
544 Ok(())
545}
546
547unsafe fn weak_str_drop(ox: OxPtrMut) {
549 unsafe {
550 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<str>>() as *mut Weak<str>);
551 }
552}
553
554unsafe fn weak_str_clone(src: OxPtrConst, dst: OxPtrMut) {
556 unsafe {
557 let value = src.get::<Weak<str>>().clone();
558 (dst.ptr().as_ptr::<Weak<str>>() as *mut Weak<str>).write(value);
559 }
560}
561
562unsafe fn weak_str_upgrade_into_fn(weak: PtrMut, strong: PtrUninit) -> Option<PtrMut> {
564 unsafe { Some(strong.put(weak.get::<Weak<str>>().upgrade()?)) }
565}
566
567unsafe impl<'a> Facet<'a> for Weak<str> {
568 const SHAPE: &'static Shape = &const {
569 const VTABLE: VTableIndirect = VTableIndirect {
570 debug: Some(weak_debug),
571 display: None,
572 hash: None,
573 invariants: None,
574 parse: None,
575 parse_bytes: None,
576 try_from: None,
577 try_into_inner: None,
578 try_borrow_inner: None,
579 partial_eq: None,
580 partial_cmp: None,
581 cmp: None,
582 };
583
584 const TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
585 drop_in_place: weak_str_drop,
586 default_in_place: None,
587 clone_into: Some(weak_str_clone),
588 is_truthy: None,
589 };
590
591 ShapeBuilder::for_sized::<Weak<str>>("Weak")
592 .type_name(weak_str_type_name)
593 .ty(Type::User(UserType::Opaque))
594 .def(Def::Pointer(PointerDef {
595 vtable: &const {
596 PointerVTable {
597 upgrade_into_fn: Some(|weak, strong| unsafe {
598 weak_str_upgrade_into_fn(weak, strong)
599 }),
600 ..PointerVTable::new()
601 }
602 },
603 pointee: Some(str::SHAPE),
604 weak: None,
605 strong: Some(<Rc<str> as Facet>::SHAPE),
606 flags: PointerFlags::WEAK,
607 known: Some(KnownPointer::RcWeak),
608 }))
609 .type_params(&[crate::TypeParam {
610 name: "T",
611 shape: str::SHAPE,
612 }])
613 .vtable_indirect(&VTABLE)
614 .type_ops_indirect(&TYPE_OPS)
615 .build()
616 };
617}
618
619fn weak_slice_type_name<'a, U: Facet<'a>>(
625 _shape: &'static Shape,
626 f: &mut core::fmt::Formatter<'_>,
627 opts: TypeNameOpts,
628) -> core::fmt::Result {
629 write!(f, "Weak")?;
630 if let Some(opts) = opts.for_children() {
631 write!(f, "<")?;
632 <[U]>::SHAPE.write_type_name(f, opts)?;
633 write!(f, ">")?;
634 } else {
635 write!(f, "<…>")?;
636 }
637 Ok(())
638}
639
640unsafe fn weak_slice_drop<U>(ox: OxPtrMut) {
642 unsafe {
643 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<[U]>>() as *mut Weak<[U]>);
644 }
645}
646
647unsafe fn weak_slice_clone<U>(src: OxPtrConst, dst: OxPtrMut) {
649 unsafe {
650 let value = src.get::<Weak<[U]>>().clone();
651 (dst.ptr().as_ptr::<Weak<[U]>>() as *mut Weak<[U]>).write(value);
652 }
653}
654
655unsafe fn weak_slice_upgrade_into_fn<'a, 'ptr, U: Facet<'a>>(
657 weak: PtrMut,
658 strong: PtrUninit,
659) -> Option<PtrMut> {
660 unsafe { Some(strong.put(weak.get::<Weak<[U]>>().upgrade()?)) }
661}
662
663unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
664 const SHAPE: &'static Shape = &const {
665 ShapeBuilder::for_sized::<Weak<[U]>>("Weak")
666 .type_name(weak_slice_type_name::<U>)
667 .ty(Type::User(UserType::Opaque))
668 .def(Def::Pointer(PointerDef {
669 vtable: &const {
670 PointerVTable {
671 upgrade_into_fn: Some(|weak, strong| unsafe {
672 weak_slice_upgrade_into_fn::<U>(weak, strong)
673 }),
674 ..PointerVTable::new()
675 }
676 },
677 pointee: Some(<[U]>::SHAPE),
678 weak: None,
679 strong: Some(<Rc<[U]> as Facet>::SHAPE),
680 flags: PointerFlags::WEAK,
681 known: Some(KnownPointer::RcWeak),
682 }))
683 .type_params(&[crate::TypeParam {
684 name: "T",
685 shape: <[U]>::SHAPE,
686 }])
687 .vtable_indirect(
688 &const {
689 VTableIndirect {
690 debug: Some(weak_debug),
691 display: None,
692 hash: None,
693 invariants: None,
694 parse: None,
695 parse_bytes: None,
696 try_from: None,
697 try_into_inner: None,
698 try_borrow_inner: None,
699 partial_eq: None,
700 partial_cmp: None,
701 cmp: None,
702 }
703 },
704 )
705 .type_ops_indirect(
706 &const {
707 TypeOpsIndirect {
708 drop_in_place: weak_slice_drop::<U>,
709 default_in_place: None,
710 clone_into: Some(weak_slice_clone::<U>),
711 is_truthy: None,
712 }
713 },
714 )
715 .build()
716 };
717}
718
719#[cfg(test)]
720mod tests {
721 use core::mem::ManuallyDrop;
722
723 use alloc::rc::{Rc, Weak as RcWeak};
724 use alloc::string::String;
725
726 use super::*;
727
728 #[test]
729 fn test_rc_type_params() {
730 let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
731 panic!("Rc<T> should only have 1 type param")
732 };
733 assert_eq!(type_param_1.shape(), i32::SHAPE);
734 }
735
736 #[test]
737 fn test_rc_vtable_1_new_borrow_drop() {
738 facet_testhelpers::setup();
739
740 let rc_shape = <Rc<String>>::SHAPE;
741 let rc_def = rc_shape
742 .def
743 .into_pointer()
744 .expect("Rc<T> should have a smart pointer definition");
745
746 let rc_uninit_ptr = rc_shape.allocate().unwrap();
748
749 let new_into_fn = rc_def
751 .vtable
752 .new_into_fn
753 .expect("Rc<T> should have new_into_fn");
754
755 let mut value = ManuallyDrop::new(String::from("example"));
757 let rc_ptr = unsafe {
758 new_into_fn(
759 rc_uninit_ptr,
760 PtrMut::new(NonNull::from(&mut value).as_ptr()),
761 )
762 };
763
764 let borrow_fn = rc_def
766 .vtable
767 .borrow_fn
768 .expect("Rc<T> should have borrow_fn");
769
770 let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
772 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
774
775 unsafe {
778 rc_shape
779 .call_drop_in_place(rc_ptr)
780 .expect("Rc<T> should have drop_in_place");
781 }
782
783 unsafe { rc_shape.deallocate_mut(rc_ptr).unwrap() };
786 }
787
788 #[test]
789 fn test_rc_vtable_2_downgrade_upgrade_drop() {
790 facet_testhelpers::setup();
791
792 let rc_shape = <Rc<String>>::SHAPE;
793 let rc_def = rc_shape
794 .def
795 .into_pointer()
796 .expect("Rc<T> should have a smart pointer definition");
797
798 let weak_shape = <RcWeak<String>>::SHAPE;
799 let weak_def = weak_shape
800 .def
801 .into_pointer()
802 .expect("RcWeak<T> should have a smart pointer definition");
803
804 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
806 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
807 let mut value = ManuallyDrop::new(String::from("example"));
808 let rc1_ptr = unsafe {
809 new_into_fn(
810 rc1_uninit_ptr,
811 PtrMut::new(NonNull::from(&mut value).as_ptr()),
812 )
813 };
814
815 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
817 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
818 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
820
821 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
823 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
824 let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
827 .expect("Upgrade should succeed while original Rc exists");
828
829 let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
831 let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
833 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
835
836 unsafe {
838 rc_shape.call_drop_in_place(rc1_ptr).unwrap();
840 rc_shape.deallocate_mut(rc1_ptr).unwrap();
841
842 rc_shape.call_drop_in_place(rc2_ptr).unwrap();
843 rc_shape.deallocate_mut(rc2_ptr).unwrap();
844
845 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
847 weak_shape.deallocate_mut(weak1_ptr).unwrap();
848 }
849 }
850
851 #[test]
852 fn test_rc_vtable_3_downgrade_drop_try_upgrade() {
853 facet_testhelpers::setup();
854
855 let rc_shape = <Rc<String>>::SHAPE;
856 let rc_def = rc_shape
857 .def
858 .into_pointer()
859 .expect("Rc<T> should have a smart pointer definition");
860
861 let weak_shape = <RcWeak<String>>::SHAPE;
862 let weak_def = weak_shape
863 .def
864 .into_pointer()
865 .expect("RcWeak<T> should have a smart pointer definition");
866
867 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
869 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
870 let mut value = ManuallyDrop::new(String::from("example"));
871 let rc1_ptr = unsafe {
872 new_into_fn(
873 rc1_uninit_ptr,
874 PtrMut::new(NonNull::from(&mut value).as_ptr()),
875 )
876 };
877
878 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
880 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
881 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
883
884 unsafe {
886 rc_shape.call_drop_in_place(rc1_ptr).unwrap();
887 rc_shape.deallocate_mut(rc1_ptr).unwrap();
888 }
889
890 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
892 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
893 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
895
896 assert!(
898 upgrade_result.is_none(),
899 "Upgrade should fail after the strong Rc is dropped"
900 );
901
902 unsafe {
904 rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
906
907 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
909 weak_shape.deallocate_mut(weak1_ptr).unwrap();
910 }
911 }
912}