Skip to main content

facet_core/impls/alloc/
rc.rs

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
13//////////////////////////////////////////////////////////////////////
14// Rc<T>
15//////////////////////////////////////////////////////////////////////
16
17/// Type name formatter for `Rc<T>`
18fn 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
34/// Drop function for `Rc<T>`
35unsafe 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
41/// Debug function for `Rc<T>`
42unsafe 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    // Try to debug the inner value if T has debug
49    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    // Fallback: just show it's an Rc
55    Some(write!(f, "Rc(...)"))
56}
57
58/// Borrow function for PointerVTable
59unsafe 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
64/// New into function for PointerVTable
65unsafe 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
74/// Downgrade into function for PointerVTable
75unsafe 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            // Rc<T> propagates T's variance
108            .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
144//////////////////////////////////////////////////////////////////////
145// Rc<str>
146//////////////////////////////////////////////////////////////////////
147
148/// Type name formatter for `Rc<str>`
149fn 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
165/// Drop function for `Rc<str>`
166unsafe 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
172/// Clone function for `Rc<str>`
173unsafe 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
180/// Debug function for `Rc<str>`
181unsafe 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
190/// Borrow function for `Rc<str>`
191unsafe 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
199/// Downgrade into function for `Rc<str>`
200unsafe 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
258//////////////////////////////////////////////////////////////////////
259// Rc<[U]>
260//////////////////////////////////////////////////////////////////////
261
262fn 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
291/// Type name formatter for `Rc<[U]>`
292fn 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
308/// Drop function for `Rc<[U]>`
309unsafe 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
315/// Debug function for `Rc<[U]>`
316unsafe 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    // Try to debug the slice if U has debug
324    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
332/// Borrow function for `Rc<[U]>`
333unsafe 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
341/// Downgrade into function for `Rc<[U]>`
342unsafe 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
417//////////////////////////////////////////////////////////////////////
418// Weak<T>
419//////////////////////////////////////////////////////////////////////
420
421/// Type name formatter for `Weak<T>`
422fn 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
438/// Drop function for `Weak<T>`
439unsafe 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
445/// Default function for `Weak<T>`
446unsafe fn weak_default<T>(ox: OxPtrUninit) -> bool {
447    unsafe { ox.put(Weak::<T>::new()) };
448    true
449}
450
451/// Clone function for `Weak<T>`
452unsafe 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
459/// Debug function for `Weak<T>`
460unsafe fn weak_debug(
461    _ox: OxPtrConst,
462    f: &mut core::fmt::Formatter<'_>,
463) -> Option<core::fmt::Result> {
464    Some(write!(f, "(Weak)"))
465}
466
467/// Upgrade into function for `Weak<T>`
468unsafe 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            // Weak<T> propagates T's variance
502            .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
538//////////////////////////////////////////////////////////////////////
539// Weak<str>
540//////////////////////////////////////////////////////////////////////
541
542/// Type name formatter for `Weak<str>`
543fn 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
559/// Drop function for `Weak<str>`
560unsafe 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
566/// Clone function for `Weak<str>`
567unsafe 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
574/// Upgrade into function for `Weak<str>`
575unsafe 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
632//////////////////////////////////////////////////////////////////////
633// Weak<[U]>
634//////////////////////////////////////////////////////////////////////
635
636/// Type name formatter for `Weak<[U]>`
637fn 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
653/// Drop function for `Weak<[U]>`
654unsafe 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
660/// Clone function for `Weak<[U]>`
661unsafe 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
668/// Upgrade into function for `Weak<[U]>`
669unsafe 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        // Allocate memory for the Rc
761        let rc_uninit_ptr = rc_shape.allocate().unwrap();
762
763        // Get the function pointer for creating a new Rc from a value
764        let new_into_fn = rc_def
765            .vtable
766            .new_into_fn
767            .expect("Rc<T> should have new_into_fn");
768
769        // Create the value and initialize the Rc
770        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        // Get the function pointer for borrowing the inner value
779        let borrow_fn = rc_def
780            .vtable
781            .borrow_fn
782            .expect("Rc<T> should have borrow_fn");
783
784        // Borrow the inner value and check it
785        let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
786        // SAFETY: borrowed_ptr points to a valid String within the Rc
787        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
788
789        // Drop the Rc in place
790        // SAFETY: rc_ptr points to a valid Rc<String>
791        unsafe {
792            rc_shape
793                .call_drop_in_place(rc_ptr)
794                .expect("Rc<T> should have drop_in_place");
795        }
796
797        // Deallocate the memory
798        // SAFETY: rc_ptr was allocated by rc_shape and is now dropped (but memory is still valid)
799        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        // 1. Create the first Rc (rc1)
819        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        // 2. Downgrade rc1 to create a weak pointer (weak1)
830        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
831        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
832        // SAFETY: rc1_ptr points to a valid Rc, weak1_uninit_ptr is allocated for a Weak
833        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
834
835        // 3. Upgrade weak1 to create a second Rc (rc2)
836        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
837        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
838        // SAFETY: weak1_ptr points to a valid Weak, rc2_uninit_ptr is allocated for an Rc.
839        // Upgrade should succeed as rc1 still exists.
840        let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
841            .expect("Upgrade should succeed while original Rc exists");
842
843        // Check the content of the upgraded Rc
844        let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
845        // SAFETY: rc2_ptr points to a valid Rc<String>
846        let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
847        // SAFETY: borrowed_ptr points to a valid String
848        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
849
850        // 4. Drop everything and free memory
851        unsafe {
852            // Drop Rcs
853            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            // Drop Weak
860            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        // 1. Create the strong Rc (rc1)
882        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        // 2. Downgrade rc1 to create a weak pointer (weak1)
893        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
894        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
895        // SAFETY: rc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
896        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
897
898        // 3. Drop and free the strong pointer (rc1)
899        unsafe {
900            rc_shape.call_drop_in_place(rc1_ptr).unwrap();
901            rc_shape.deallocate_mut(rc1_ptr).unwrap();
902        }
903
904        // 4. Attempt to upgrade the weak pointer (weak1)
905        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
906        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
907        // SAFETY: weak1_ptr is valid (though points to dropped data), rc2_uninit_ptr is allocated for Rc
908        let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
909
910        // Assert that the upgrade failed
911        assert!(
912            upgrade_result.is_none(),
913            "Upgrade should fail after the strong Rc is dropped"
914        );
915
916        // 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
917        unsafe {
918            // Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
919            rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
920
921            // Drop and deallocate the weak pointer
922            weak_shape.call_drop_in_place(weak1_ptr).unwrap();
923            weak_shape.deallocate_mut(weak1_ptr).unwrap();
924        }
925    }
926}