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, PointerDef, PointerFlags, PointerVTable,
9    PtrConst, PtrMut, PtrUninit, Shape, ShapeBuilder, SliceBuilderVTable, Type, TypeNameOpts,
10    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 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 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
71/// Downgrade into function for PointerVTable
72unsafe 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            // Rc<T> propagates T's variance
105            .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
141//////////////////////////////////////////////////////////////////////
142// Rc<str>
143//////////////////////////////////////////////////////////////////////
144
145/// Type name formatter for `Rc<str>`
146fn 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
162/// Drop function for `Rc<str>`
163unsafe 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
169/// Clone function for `Rc<str>`
170unsafe 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
177/// Debug function for `Rc<str>`
178unsafe 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
187/// Borrow function for `Rc<str>`
188unsafe 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
196/// Downgrade into function for `Rc<str>`
197unsafe 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
255//////////////////////////////////////////////////////////////////////
256// Rc<[U]>
257//////////////////////////////////////////////////////////////////////
258
259fn 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
288/// Type name formatter for `Rc<[U]>`
289fn 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
305/// Drop function for `Rc<[U]>`
306unsafe 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
312/// Debug function for `Rc<[U]>`
313unsafe 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    // Try to debug the slice if U has debug
321    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
329/// Borrow function for `Rc<[U]>`
330unsafe 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
338/// Downgrade into function for `Rc<[U]>`
339unsafe 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
414//////////////////////////////////////////////////////////////////////
415// Weak<T>
416//////////////////////////////////////////////////////////////////////
417
418/// Type name formatter for `Weak<T>`
419fn 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
435/// Drop function for `Weak<T>`
436unsafe 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
442/// Default function for `Weak<T>`
443unsafe 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
449/// Clone function for `Weak<T>`
450unsafe 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
457/// Debug function for `Weak<T>`
458unsafe fn weak_debug(
459    _ox: OxPtrConst,
460    f: &mut core::fmt::Formatter<'_>,
461) -> Option<core::fmt::Result> {
462    Some(write!(f, "(Weak)"))
463}
464
465/// Upgrade into function for `Weak<T>`
466unsafe 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            // Weak<T> propagates T's variance
500            .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
536//////////////////////////////////////////////////////////////////////
537// Weak<str>
538//////////////////////////////////////////////////////////////////////
539
540/// Type name formatter for `Weak<str>`
541fn 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
557/// Drop function for `Weak<str>`
558unsafe 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
564/// Clone function for `Weak<str>`
565unsafe 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
572/// Upgrade into function for `Weak<str>`
573unsafe 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
630//////////////////////////////////////////////////////////////////////
631// Weak<[U]>
632//////////////////////////////////////////////////////////////////////
633
634/// Type name formatter for `Weak<[U]>`
635fn 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
651/// Drop function for `Weak<[U]>`
652unsafe 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
658/// Clone function for `Weak<[U]>`
659unsafe 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
666/// Upgrade into function for `Weak<[U]>`
667unsafe 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        // Allocate memory for the Rc
759        let rc_uninit_ptr = rc_shape.allocate().unwrap();
760
761        // Get the function pointer for creating a new Rc from a value
762        let new_into_fn = rc_def
763            .vtable
764            .new_into_fn
765            .expect("Rc<T> should have new_into_fn");
766
767        // Create the value and initialize the Rc
768        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        // Get the function pointer for borrowing the inner value
777        let borrow_fn = rc_def
778            .vtable
779            .borrow_fn
780            .expect("Rc<T> should have borrow_fn");
781
782        // Borrow the inner value and check it
783        let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
784        // SAFETY: borrowed_ptr points to a valid String within the Rc
785        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
786
787        // Drop the Rc in place
788        // SAFETY: rc_ptr points to a valid Rc<String>
789        unsafe {
790            rc_shape
791                .call_drop_in_place(rc_ptr)
792                .expect("Rc<T> should have drop_in_place");
793        }
794
795        // Deallocate the memory
796        // SAFETY: rc_ptr was allocated by rc_shape and is now dropped (but memory is still valid)
797        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        // 1. Create the first Rc (rc1)
817        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        // 2. Downgrade rc1 to create a weak pointer (weak1)
828        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
829        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
830        // SAFETY: rc1_ptr points to a valid Rc, weak1_uninit_ptr is allocated for a Weak
831        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
832
833        // 3. Upgrade weak1 to create a second Rc (rc2)
834        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
835        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
836        // SAFETY: weak1_ptr points to a valid Weak, rc2_uninit_ptr is allocated for an Rc.
837        // Upgrade should succeed as rc1 still exists.
838        let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
839            .expect("Upgrade should succeed while original Rc exists");
840
841        // Check the content of the upgraded Rc
842        let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
843        // SAFETY: rc2_ptr points to a valid Rc<String>
844        let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
845        // SAFETY: borrowed_ptr points to a valid String
846        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
847
848        // 4. Drop everything and free memory
849        unsafe {
850            // Drop Rcs
851            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            // Drop Weak
858            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        // 1. Create the strong Rc (rc1)
880        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        // 2. Downgrade rc1 to create a weak pointer (weak1)
891        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
892        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
893        // SAFETY: rc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
894        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
895
896        // 3. Drop and free the strong pointer (rc1)
897        unsafe {
898            rc_shape.call_drop_in_place(rc1_ptr).unwrap();
899            rc_shape.deallocate_mut(rc1_ptr).unwrap();
900        }
901
902        // 4. Attempt to upgrade the weak pointer (weak1)
903        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
904        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
905        // SAFETY: weak1_ptr is valid (though points to dropped data), rc2_uninit_ptr is allocated for Rc
906        let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
907
908        // Assert that the upgrade failed
909        assert!(
910            upgrade_result.is_none(),
911            "Upgrade should fail after the strong Rc is dropped"
912        );
913
914        // 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
915        unsafe {
916            // Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
917            rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
918
919            // Drop and deallocate the weak pointer
920            weak_shape.call_drop_in_place(weak1_ptr).unwrap();
921            weak_shape.deallocate_mut(weak1_ptr).unwrap();
922        }
923    }
924}