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