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, Variance, VarianceDep, VarianceDesc,
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 .module_path("alloc::rc")
80 .type_name(rc_type_name::<T>)
81 .ty(Type::User(UserType::Opaque))
82 .def(Def::Pointer(PointerDef {
83 vtable: &const {
84 PointerVTable {
85 borrow_fn: Some(rc_borrow_fn::<T>),
86 new_into_fn: Some(rc_new_into_fn::<T>),
87 downgrade_into_fn: Some(|strong, weak| unsafe {
88 rc_downgrade_into_fn::<T>(strong, weak)
89 }),
90 ..PointerVTable::new()
91 }
92 },
93 pointee: Some(T::SHAPE),
94 weak: Some(|| <Weak<T> as Facet>::SHAPE),
95 strong: None,
96 flags: PointerFlags::EMPTY,
97 known: Some(KnownPointer::Rc),
98 }))
99 .type_params(&[crate::TypeParam {
100 name: "T",
101 shape: T::SHAPE,
102 }])
103 .inner(T::SHAPE)
104 .variance(VarianceDesc {
106 base: Variance::Bivariant,
107 deps: &const { [VarianceDep::covariant(T::SHAPE)] },
108 })
109 .vtable_indirect(
110 &const {
111 VTableIndirect {
112 debug: Some(rc_debug::<T>),
113 display: None,
114 hash: None,
115 invariants: None,
116 parse: None,
117 parse_bytes: None,
118 try_from: None,
119 try_into_inner: None,
120 try_borrow_inner: None,
121 partial_eq: None,
122 partial_cmp: None,
123 cmp: None,
124 }
125 },
126 )
127 .type_ops_indirect(
128 &const {
129 TypeOpsIndirect {
130 drop_in_place: rc_drop::<T>,
131 default_in_place: None,
132 clone_into: None,
133 is_truthy: None,
134 }
135 },
136 )
137 .build()
138 };
139}
140
141fn rc_str_type_name(
147 _shape: &'static Shape,
148 f: &mut core::fmt::Formatter<'_>,
149 opts: TypeNameOpts,
150) -> core::fmt::Result {
151 write!(f, "Rc")?;
152 if let Some(opts) = opts.for_children() {
153 write!(f, "<")?;
154 str::SHAPE.write_type_name(f, opts)?;
155 write!(f, ">")?;
156 } else {
157 write!(f, "<…>")?;
158 }
159 Ok(())
160}
161
162unsafe fn rc_str_drop(ox: OxPtrMut) {
164 unsafe {
165 core::ptr::drop_in_place(ox.ptr().as_ptr::<Rc<str>>() as *mut Rc<str>);
166 }
167}
168
169unsafe fn rc_str_clone(src: OxPtrConst, dst: OxPtrMut) {
171 unsafe {
172 let value = src.get::<Rc<str>>().clone();
173 (dst.ptr().as_ptr::<Rc<str>>() as *mut Rc<str>).write(value);
174 }
175}
176
177unsafe fn rc_str_debug(
179 ox: OxPtrConst,
180 f: &mut core::fmt::Formatter<'_>,
181) -> Option<core::fmt::Result> {
182 let rc = unsafe { ox.get::<Rc<str>>() };
183 let s: &str = rc;
184 Some(write!(f, "Rc({s:?})"))
185}
186
187unsafe fn rc_str_borrow_fn(this: PtrConst) -> PtrConst {
189 unsafe {
190 let concrete = this.get::<Rc<str>>();
191 let s: &str = concrete;
192 PtrConst::new(NonNull::from(s).as_ptr())
193 }
194}
195
196unsafe fn rc_str_downgrade_into_fn(strong: PtrMut, weak: PtrUninit) -> PtrMut {
198 unsafe { weak.put(Rc::downgrade(strong.get::<Rc<str>>())) }
199}
200
201unsafe impl<'a> Facet<'a> for Rc<str> {
202 const SHAPE: &'static Shape = &const {
203 const VTABLE: VTableIndirect = VTableIndirect {
204 debug: Some(rc_str_debug),
205 display: None,
206 hash: None,
207 invariants: None,
208 parse: None,
209 parse_bytes: None,
210 try_from: None,
211 try_into_inner: None,
212 try_borrow_inner: None,
213 partial_eq: None,
214 partial_cmp: None,
215 cmp: None,
216 };
217
218 const TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
219 drop_in_place: rc_str_drop,
220 default_in_place: None,
221 clone_into: Some(rc_str_clone),
222 is_truthy: None,
223 };
224
225 ShapeBuilder::for_sized::<Rc<str>>("Rc")
226 .module_path("alloc::rc")
227 .type_name(rc_str_type_name)
228 .ty(Type::User(UserType::Opaque))
229 .def(Def::Pointer(PointerDef {
230 vtable: &const {
231 PointerVTable {
232 borrow_fn: Some(rc_str_borrow_fn),
233 downgrade_into_fn: Some(|strong, weak| unsafe {
234 rc_str_downgrade_into_fn(strong, weak)
235 }),
236 ..PointerVTable::new()
237 }
238 },
239 pointee: Some(str::SHAPE),
240 weak: Some(|| <Weak<str> as Facet>::SHAPE),
241 strong: None,
242 flags: PointerFlags::EMPTY,
243 known: Some(KnownPointer::Rc),
244 }))
245 .type_params(&[crate::TypeParam {
246 name: "T",
247 shape: str::SHAPE,
248 }])
249 .vtable_indirect(&VTABLE)
250 .type_ops_indirect(&TYPE_OPS)
251 .build()
252 };
253}
254
255fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut {
260 let v = Box::new(Vec::<U>::new());
261 let raw = Box::into_raw(v);
262 PtrMut::new(unsafe { NonNull::new_unchecked(raw as *mut u8) }.as_ptr())
263}
264
265fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
266 unsafe {
267 let vec = builder.as_mut::<Vec<U>>();
268 let value = item.read::<U>();
269 vec.push(value);
270 }
271}
272
273fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut) -> PtrConst {
274 unsafe {
275 let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
276 let rc: Rc<[U]> = (*vec_box).into();
277 let rc_box = Box::new(rc);
278 PtrConst::new(NonNull::new_unchecked(Box::into_raw(rc_box) as *mut u8).as_ptr())
279 }
280}
281
282fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut) {
283 unsafe {
284 let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
285 }
286}
287
288fn rc_slice_type_name<'a, U: Facet<'a>>(
290 _shape: &'static Shape,
291 f: &mut core::fmt::Formatter<'_>,
292 opts: TypeNameOpts,
293) -> core::fmt::Result {
294 write!(f, "Rc")?;
295 if let Some(opts) = opts.for_children() {
296 write!(f, "<")?;
297 <[U]>::SHAPE.write_type_name(f, opts)?;
298 write!(f, ">")?;
299 } else {
300 write!(f, "<…>")?;
301 }
302 Ok(())
303}
304
305unsafe fn rc_slice_drop<U>(ox: OxPtrMut) {
307 unsafe {
308 core::ptr::drop_in_place(ox.ptr().as_ptr::<Rc<[U]>>() as *mut Rc<[U]>);
309 }
310}
311
312unsafe fn rc_slice_debug<'a, U: Facet<'a>>(
314 ox: OxPtrConst,
315 f: &mut core::fmt::Formatter<'_>,
316) -> Option<core::fmt::Result> {
317 let rc = unsafe { ox.get::<Rc<[U]>>() };
318 let slice: &[U] = rc;
319
320 let slice_ptr = PtrConst::new(NonNull::from(slice).as_ptr());
322 if let Some(result) = unsafe { <[U]>::SHAPE.call_debug(slice_ptr, f) } {
323 return Some(result);
324 }
325
326 Some(write!(f, "Rc([...])"))
327}
328
329unsafe fn rc_slice_borrow_fn<U>(this: PtrConst) -> PtrConst {
331 unsafe {
332 let concrete = this.get::<Rc<[U]>>();
333 let s: &[U] = concrete;
334 PtrConst::new(NonNull::from(s).as_ptr())
335 }
336}
337
338unsafe fn rc_slice_downgrade_into_fn<'a, 'ptr, U: Facet<'a>>(
340 strong: PtrMut,
341 weak: PtrUninit,
342) -> PtrMut {
343 unsafe { weak.put(Rc::downgrade(strong.get::<Rc<[U]>>())) }
344}
345
346unsafe impl<'a, U: Facet<'a>> Facet<'a> for Rc<[U]> {
347 const SHAPE: &'static Shape = &const {
348 ShapeBuilder::for_sized::<Rc<[U]>>("Rc")
349 .module_path("alloc::rc")
350 .type_name(rc_slice_type_name::<U>)
351 .ty(Type::User(UserType::Opaque))
352 .def(Def::Pointer(PointerDef {
353 vtable: &const {
354 PointerVTable {
355 borrow_fn: Some(rc_slice_borrow_fn::<U>),
356 downgrade_into_fn: Some(|strong, weak| unsafe {
357 rc_slice_downgrade_into_fn::<U>(strong, weak)
358 }),
359 slice_builder_vtable: Some(
360 &const {
361 SliceBuilderVTable::new(
362 slice_builder_new::<U>,
363 slice_builder_push::<U>,
364 slice_builder_convert::<U>,
365 slice_builder_free::<U>,
366 )
367 },
368 ),
369 ..PointerVTable::new()
370 }
371 },
372 pointee: Some(<[U]>::SHAPE),
373 weak: Some(|| <Weak<[U]> as Facet>::SHAPE),
374 strong: None,
375 flags: PointerFlags::EMPTY,
376 known: Some(KnownPointer::Rc),
377 }))
378 .type_params(&[crate::TypeParam {
379 name: "T",
380 shape: <[U]>::SHAPE,
381 }])
382 .vtable_indirect(
383 &const {
384 VTableIndirect {
385 debug: Some(rc_slice_debug::<U>),
386 display: None,
387 hash: None,
388 invariants: None,
389 parse: None,
390 parse_bytes: None,
391 try_from: None,
392 try_into_inner: None,
393 try_borrow_inner: None,
394 partial_eq: None,
395 partial_cmp: None,
396 cmp: None,
397 }
398 },
399 )
400 .type_ops_indirect(
401 &const {
402 TypeOpsIndirect {
403 drop_in_place: rc_slice_drop::<U>,
404 default_in_place: None,
405 clone_into: None,
406 is_truthy: None,
407 }
408 },
409 )
410 .build()
411 };
412}
413
414fn weak_type_name<'a, T: Facet<'a>>(
420 _shape: &'static Shape,
421 f: &mut core::fmt::Formatter<'_>,
422 opts: TypeNameOpts,
423) -> core::fmt::Result {
424 write!(f, "Weak")?;
425 if let Some(opts) = opts.for_children() {
426 write!(f, "<")?;
427 T::SHAPE.write_type_name(f, opts)?;
428 write!(f, ">")?;
429 } else {
430 write!(f, "<…>")?;
431 }
432 Ok(())
433}
434
435unsafe fn weak_drop<T>(ox: OxPtrMut) {
437 unsafe {
438 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>);
439 }
440}
441
442unsafe fn weak_default<T>(ox: OxPtrMut) {
444 unsafe {
445 (ox.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(Weak::<T>::new());
446 }
447}
448
449unsafe fn weak_clone<T>(src: OxPtrConst, dst: OxPtrMut) {
451 unsafe {
452 let value = src.get::<Weak<T>>().clone();
453 (dst.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(value);
454 }
455}
456
457unsafe fn weak_debug(
459 _ox: OxPtrConst,
460 f: &mut core::fmt::Formatter<'_>,
461) -> Option<core::fmt::Result> {
462 Some(write!(f, "(Weak)"))
463}
464
465unsafe fn weak_upgrade_into_fn<'a, 'ptr, T: Facet<'a>>(
467 weak: PtrMut,
468 strong: PtrUninit,
469) -> Option<PtrMut> {
470 unsafe { Some(strong.put(weak.get::<Weak<T>>().upgrade()?)) }
471}
472
473unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
474 const SHAPE: &'static Shape = &const {
475 ShapeBuilder::for_sized::<Weak<T>>("Weak")
476 .module_path("alloc::rc")
477 .type_name(weak_type_name::<T>)
478 .ty(Type::User(UserType::Opaque))
479 .def(Def::Pointer(PointerDef {
480 vtable: &const {
481 PointerVTable {
482 upgrade_into_fn: Some(|weak, strong| unsafe {
483 weak_upgrade_into_fn::<T>(weak, strong)
484 }),
485 ..PointerVTable::new()
486 }
487 },
488 pointee: Some(T::SHAPE),
489 weak: None,
490 strong: Some(<Rc<T> as Facet>::SHAPE),
491 flags: PointerFlags::WEAK,
492 known: Some(KnownPointer::RcWeak),
493 }))
494 .type_params(&[crate::TypeParam {
495 name: "T",
496 shape: T::SHAPE,
497 }])
498 .inner(T::SHAPE)
499 .variance(VarianceDesc {
501 base: Variance::Bivariant,
502 deps: &const { [VarianceDep::covariant(T::SHAPE)] },
503 })
504 .vtable_indirect(
505 &const {
506 VTableIndirect {
507 debug: Some(weak_debug),
508 display: None,
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 )
522 .type_ops_indirect(
523 &const {
524 TypeOpsIndirect {
525 drop_in_place: weak_drop::<T>,
526 default_in_place: Some(weak_default::<T>),
527 clone_into: Some(weak_clone::<T>),
528 is_truthy: None,
529 }
530 },
531 )
532 .build()
533 };
534}
535
536fn weak_str_type_name(
542 _shape: &'static Shape,
543 f: &mut core::fmt::Formatter<'_>,
544 opts: TypeNameOpts,
545) -> core::fmt::Result {
546 write!(f, "Weak")?;
547 if let Some(opts) = opts.for_children() {
548 write!(f, "<")?;
549 str::SHAPE.write_type_name(f, opts)?;
550 write!(f, ">")?;
551 } else {
552 write!(f, "<…>")?;
553 }
554 Ok(())
555}
556
557unsafe fn weak_str_drop(ox: OxPtrMut) {
559 unsafe {
560 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<str>>() as *mut Weak<str>);
561 }
562}
563
564unsafe fn weak_str_clone(src: OxPtrConst, dst: OxPtrMut) {
566 unsafe {
567 let value = src.get::<Weak<str>>().clone();
568 (dst.ptr().as_ptr::<Weak<str>>() as *mut Weak<str>).write(value);
569 }
570}
571
572unsafe fn weak_str_upgrade_into_fn(weak: PtrMut, strong: PtrUninit) -> Option<PtrMut> {
574 unsafe { Some(strong.put(weak.get::<Weak<str>>().upgrade()?)) }
575}
576
577unsafe impl<'a> Facet<'a> for Weak<str> {
578 const SHAPE: &'static Shape = &const {
579 const VTABLE: VTableIndirect = VTableIndirect {
580 debug: Some(weak_debug),
581 display: None,
582 hash: None,
583 invariants: None,
584 parse: None,
585 parse_bytes: None,
586 try_from: None,
587 try_into_inner: None,
588 try_borrow_inner: None,
589 partial_eq: None,
590 partial_cmp: None,
591 cmp: None,
592 };
593
594 const TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
595 drop_in_place: weak_str_drop,
596 default_in_place: None,
597 clone_into: Some(weak_str_clone),
598 is_truthy: None,
599 };
600
601 ShapeBuilder::for_sized::<Weak<str>>("Weak")
602 .module_path("alloc::rc")
603 .type_name(weak_str_type_name)
604 .ty(Type::User(UserType::Opaque))
605 .def(Def::Pointer(PointerDef {
606 vtable: &const {
607 PointerVTable {
608 upgrade_into_fn: Some(|weak, strong| unsafe {
609 weak_str_upgrade_into_fn(weak, strong)
610 }),
611 ..PointerVTable::new()
612 }
613 },
614 pointee: Some(str::SHAPE),
615 weak: None,
616 strong: Some(<Rc<str> as Facet>::SHAPE),
617 flags: PointerFlags::WEAK,
618 known: Some(KnownPointer::RcWeak),
619 }))
620 .type_params(&[crate::TypeParam {
621 name: "T",
622 shape: str::SHAPE,
623 }])
624 .vtable_indirect(&VTABLE)
625 .type_ops_indirect(&TYPE_OPS)
626 .build()
627 };
628}
629
630fn weak_slice_type_name<'a, U: Facet<'a>>(
636 _shape: &'static Shape,
637 f: &mut core::fmt::Formatter<'_>,
638 opts: TypeNameOpts,
639) -> core::fmt::Result {
640 write!(f, "Weak")?;
641 if let Some(opts) = opts.for_children() {
642 write!(f, "<")?;
643 <[U]>::SHAPE.write_type_name(f, opts)?;
644 write!(f, ">")?;
645 } else {
646 write!(f, "<…>")?;
647 }
648 Ok(())
649}
650
651unsafe fn weak_slice_drop<U>(ox: OxPtrMut) {
653 unsafe {
654 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<[U]>>() as *mut Weak<[U]>);
655 }
656}
657
658unsafe fn weak_slice_clone<U>(src: OxPtrConst, dst: OxPtrMut) {
660 unsafe {
661 let value = src.get::<Weak<[U]>>().clone();
662 (dst.ptr().as_ptr::<Weak<[U]>>() as *mut Weak<[U]>).write(value);
663 }
664}
665
666unsafe fn weak_slice_upgrade_into_fn<'a, 'ptr, U: Facet<'a>>(
668 weak: PtrMut,
669 strong: PtrUninit,
670) -> Option<PtrMut> {
671 unsafe { Some(strong.put(weak.get::<Weak<[U]>>().upgrade()?)) }
672}
673
674unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
675 const SHAPE: &'static Shape = &const {
676 ShapeBuilder::for_sized::<Weak<[U]>>("Weak")
677 .module_path("alloc::rc")
678 .type_name(weak_slice_type_name::<U>)
679 .ty(Type::User(UserType::Opaque))
680 .def(Def::Pointer(PointerDef {
681 vtable: &const {
682 PointerVTable {
683 upgrade_into_fn: Some(|weak, strong| unsafe {
684 weak_slice_upgrade_into_fn::<U>(weak, strong)
685 }),
686 ..PointerVTable::new()
687 }
688 },
689 pointee: Some(<[U]>::SHAPE),
690 weak: None,
691 strong: Some(<Rc<[U]> as Facet>::SHAPE),
692 flags: PointerFlags::WEAK,
693 known: Some(KnownPointer::RcWeak),
694 }))
695 .type_params(&[crate::TypeParam {
696 name: "T",
697 shape: <[U]>::SHAPE,
698 }])
699 .vtable_indirect(
700 &const {
701 VTableIndirect {
702 debug: Some(weak_debug),
703 display: None,
704 hash: None,
705 invariants: None,
706 parse: None,
707 parse_bytes: None,
708 try_from: None,
709 try_into_inner: None,
710 try_borrow_inner: None,
711 partial_eq: None,
712 partial_cmp: None,
713 cmp: None,
714 }
715 },
716 )
717 .type_ops_indirect(
718 &const {
719 TypeOpsIndirect {
720 drop_in_place: weak_slice_drop::<U>,
721 default_in_place: None,
722 clone_into: Some(weak_slice_clone::<U>),
723 is_truthy: None,
724 }
725 },
726 )
727 .build()
728 };
729}
730
731#[cfg(test)]
732mod tests {
733 use core::mem::ManuallyDrop;
734
735 use alloc::rc::{Rc, Weak as RcWeak};
736 use alloc::string::String;
737
738 use super::*;
739
740 #[test]
741 fn test_rc_type_params() {
742 let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
743 panic!("Rc<T> should only have 1 type param")
744 };
745 assert_eq!(type_param_1.shape(), i32::SHAPE);
746 }
747
748 #[test]
749 fn test_rc_vtable_1_new_borrow_drop() {
750 facet_testhelpers::setup();
751
752 let rc_shape = <Rc<String>>::SHAPE;
753 let rc_def = rc_shape
754 .def
755 .into_pointer()
756 .expect("Rc<T> should have a smart pointer definition");
757
758 let rc_uninit_ptr = rc_shape.allocate().unwrap();
760
761 let new_into_fn = rc_def
763 .vtable
764 .new_into_fn
765 .expect("Rc<T> should have new_into_fn");
766
767 let mut value = ManuallyDrop::new(String::from("example"));
769 let rc_ptr = unsafe {
770 new_into_fn(
771 rc_uninit_ptr,
772 PtrMut::new(NonNull::from(&mut value).as_ptr()),
773 )
774 };
775
776 let borrow_fn = rc_def
778 .vtable
779 .borrow_fn
780 .expect("Rc<T> should have borrow_fn");
781
782 let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
784 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
786
787 unsafe {
790 rc_shape
791 .call_drop_in_place(rc_ptr)
792 .expect("Rc<T> should have drop_in_place");
793 }
794
795 unsafe { rc_shape.deallocate_mut(rc_ptr).unwrap() };
798 }
799
800 #[test]
801 fn test_rc_vtable_2_downgrade_upgrade_drop() {
802 facet_testhelpers::setup();
803
804 let rc_shape = <Rc<String>>::SHAPE;
805 let rc_def = rc_shape
806 .def
807 .into_pointer()
808 .expect("Rc<T> should have a smart pointer definition");
809
810 let weak_shape = <RcWeak<String>>::SHAPE;
811 let weak_def = weak_shape
812 .def
813 .into_pointer()
814 .expect("RcWeak<T> should have a smart pointer definition");
815
816 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
818 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
819 let mut value = ManuallyDrop::new(String::from("example"));
820 let rc1_ptr = unsafe {
821 new_into_fn(
822 rc1_uninit_ptr,
823 PtrMut::new(NonNull::from(&mut value).as_ptr()),
824 )
825 };
826
827 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
829 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
830 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
832
833 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
835 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
836 let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
839 .expect("Upgrade should succeed while original Rc exists");
840
841 let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
843 let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
845 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
847
848 unsafe {
850 rc_shape.call_drop_in_place(rc1_ptr).unwrap();
852 rc_shape.deallocate_mut(rc1_ptr).unwrap();
853
854 rc_shape.call_drop_in_place(rc2_ptr).unwrap();
855 rc_shape.deallocate_mut(rc2_ptr).unwrap();
856
857 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
859 weak_shape.deallocate_mut(weak1_ptr).unwrap();
860 }
861 }
862
863 #[test]
864 fn test_rc_vtable_3_downgrade_drop_try_upgrade() {
865 facet_testhelpers::setup();
866
867 let rc_shape = <Rc<String>>::SHAPE;
868 let rc_def = rc_shape
869 .def
870 .into_pointer()
871 .expect("Rc<T> should have a smart pointer definition");
872
873 let weak_shape = <RcWeak<String>>::SHAPE;
874 let weak_def = weak_shape
875 .def
876 .into_pointer()
877 .expect("RcWeak<T> should have a smart pointer definition");
878
879 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
881 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
882 let mut value = ManuallyDrop::new(String::from("example"));
883 let rc1_ptr = unsafe {
884 new_into_fn(
885 rc1_uninit_ptr,
886 PtrMut::new(NonNull::from(&mut value).as_ptr()),
887 )
888 };
889
890 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
892 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
893 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
895
896 unsafe {
898 rc_shape.call_drop_in_place(rc1_ptr).unwrap();
899 rc_shape.deallocate_mut(rc1_ptr).unwrap();
900 }
901
902 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
904 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
905 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
907
908 assert!(
910 upgrade_result.is_none(),
911 "Upgrade should fail after the strong Rc is dropped"
912 );
913
914 unsafe {
916 rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
918
919 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
921 weak_shape.deallocate_mut(weak1_ptr).unwrap();
922 }
923 }
924}