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