facet_core/impls_alloc/
smartptr.rs

1use core::alloc::Layout;
2
3use crate::{
4    ConstTypeId, Def, Facet, KnownSmartPointer, Opaque, PtrConst, PtrMut, PtrUninit, Shape,
5    SmartPointerDef, SmartPointerFlags, SmartPointerVTable, TryBorrowInnerError, TryFromInnerError,
6    TryIntoInnerError, value_vtable, value_vtable_inner,
7};
8
9unsafe impl<'a, T: Facet<'a>> Facet<'a> for alloc::sync::Arc<T> {
10    const SHAPE: &'static crate::Shape = &const {
11        // Define the functions for transparent conversion between Arc<T> and T
12        unsafe fn try_from_inner<'a, 'src, 'dst, T: Facet<'a>>(
13            src_ptr: PtrConst<'src>,
14            src_shape: &'static Shape,
15            dst: PtrUninit<'dst>,
16        ) -> Result<PtrMut<'dst>, TryFromInnerError> {
17            if src_shape.id != T::SHAPE.id {
18                return Err(TryFromInnerError::UnsupportedSourceShape {
19                    src_shape,
20                    expected: &[T::SHAPE],
21                });
22            }
23            let t = unsafe { src_ptr.read::<T>() };
24            let arc = alloc::sync::Arc::new(t);
25            Ok(unsafe { dst.put(arc) })
26        }
27
28        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
29            src_ptr: PtrConst<'src>,
30            dst: PtrUninit<'dst>,
31        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
32            let arc = unsafe { src_ptr.get::<alloc::sync::Arc<T>>() };
33            match alloc::sync::Arc::try_unwrap(arc.clone()) {
34                Ok(t) => Ok(unsafe { dst.put(t) }),
35                Err(_) => Err(TryIntoInnerError::Unavailable),
36            }
37        }
38
39        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
40            src_ptr: PtrConst<'src>,
41        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
42            let arc = unsafe { src_ptr.get::<alloc::sync::Arc<T>>() };
43            Ok(PtrConst::new(&**arc))
44        }
45
46        // Function to return inner type's shape
47        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
48            T::SHAPE
49        }
50
51        crate::Shape::builder()
52            .id(ConstTypeId::of::<Self>())
53            .layout(Layout::new::<Self>())
54            .type_params(&[crate::TypeParam {
55                name: "T",
56                shape: || T::SHAPE,
57            }])
58            .def(Def::SmartPointer(
59                SmartPointerDef::builder()
60                    .pointee(T::SHAPE)
61                    .flags(SmartPointerFlags::ATOMIC)
62                    .known(KnownSmartPointer::Arc)
63                    .weak(|| <alloc::sync::Weak<T> as Facet>::SHAPE)
64                    .vtable(
65                        &const {
66                            SmartPointerVTable::builder()
67                                .borrow_fn(|this| {
68                                    let ptr = Self::as_ptr(unsafe { this.get() });
69                                    PtrConst::new(ptr)
70                                })
71                                .new_into_fn(|this, ptr| {
72                                    let t = unsafe { ptr.read::<T>() };
73                                    let arc = alloc::sync::Arc::new(t);
74                                    unsafe { this.put(arc) }
75                                })
76                                .downgrade_into_fn(|strong, weak| unsafe {
77                                    weak.put(alloc::sync::Arc::downgrade(strong.get::<Self>()))
78                                })
79                                .build()
80                        },
81                    )
82                    .build(),
83            ))
84            .vtable(
85                &const {
86                    let mut vtable =
87                        value_vtable_inner!(alloc::sync::Arc<T>, |f, _opts| write!(f, "Arc"));
88                    vtable.try_from_inner = Some(try_from_inner::<T>);
89                    vtable.try_into_inner = Some(try_into_inner::<T>);
90                    vtable.try_borrow_inner = Some(try_borrow_inner::<T>);
91                    vtable
92                },
93            )
94            .inner(inner_shape::<T>)
95            .build()
96    };
97}
98
99unsafe impl<'a, T: Facet<'a>> Facet<'a> for alloc::sync::Weak<T> {
100    const SHAPE: &'static crate::Shape = &const {
101        // Function to return inner type's shape
102        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
103            T::SHAPE
104        }
105
106        crate::Shape::builder()
107            .id(ConstTypeId::of::<Self>())
108            .layout(Layout::new::<Self>())
109            .type_params(&[crate::TypeParam {
110                name: "T",
111                shape: || T::SHAPE,
112            }])
113            .def(Def::SmartPointer(
114                SmartPointerDef::builder()
115                    .pointee(T::SHAPE)
116                    .flags(SmartPointerFlags::ATOMIC.union(SmartPointerFlags::WEAK))
117                    .known(KnownSmartPointer::ArcWeak)
118                    .strong(|| <alloc::sync::Arc<T> as Facet>::SHAPE)
119                    .vtable(
120                        &const {
121                            SmartPointerVTable::builder()
122                                .upgrade_into_fn(|weak, strong| unsafe {
123                                    Some(strong.put(weak.get::<Self>().upgrade()?))
124                                })
125                                .build()
126                        },
127                    )
128                    .build(),
129            ))
130            .vtable(
131                &const { value_vtable_inner!(alloc::sync::Arc<T>, |f, _opts| write!(f, "Arc")) },
132            )
133            .inner(inner_shape::<T>)
134            .build()
135    };
136}
137
138unsafe impl<'a, T: 'a> Facet<'a> for Opaque<alloc::sync::Arc<T>> {
139    const SHAPE: &'static crate::Shape = &const {
140        crate::Shape::builder()
141            .id(ConstTypeId::of::<Self>())
142            .layout(Layout::new::<Self>())
143            .def(Def::SmartPointer(
144                SmartPointerDef::builder()
145                    .flags(SmartPointerFlags::ATOMIC)
146                    .known(KnownSmartPointer::Arc)
147                    .vtable(
148                        &const {
149                            SmartPointerVTable::builder()
150                                .borrow_fn(|this| {
151                                    let ptr = alloc::sync::Arc::<T>::as_ptr(unsafe { this.get() });
152                                    PtrConst::new(ptr)
153                                })
154                                .new_into_fn(|this, ptr| {
155                                    let t = unsafe { ptr.read::<T>() };
156                                    let arc = alloc::sync::Arc::new(t);
157                                    unsafe { this.put(arc) }
158                                })
159                                .build()
160                        },
161                    )
162                    .build(),
163            ))
164            .vtable(
165                &const { value_vtable_inner!(alloc::sync::Arc<T>, |f, _opts| write!(f, "Arc")) },
166            )
167            .build()
168    };
169}
170
171unsafe impl<'a, T: Facet<'a>> Facet<'a> for alloc::rc::Rc<T> {
172    const SHAPE: &'static crate::Shape = &const {
173        // Define the functions for transparent conversion between Rc<T> and T
174        unsafe fn try_from_inner<'a, 'src, 'dst, T: Facet<'a>>(
175            src_ptr: PtrConst<'src>,
176            src_shape: &'static Shape,
177            dst: PtrUninit<'dst>,
178        ) -> Result<PtrMut<'dst>, TryFromInnerError> {
179            if src_shape.id != T::SHAPE.id {
180                return Err(TryFromInnerError::UnsupportedSourceShape {
181                    src_shape,
182                    expected: &[T::SHAPE],
183                });
184            }
185            let t = unsafe { src_ptr.read::<T>() };
186            let rc = alloc::rc::Rc::new(t);
187            Ok(unsafe { dst.put(rc) })
188        }
189
190        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
191            src_ptr: PtrConst<'src>,
192            dst: PtrUninit<'dst>,
193        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
194            let rc = unsafe { src_ptr.get::<alloc::rc::Rc<T>>() };
195            match alloc::rc::Rc::try_unwrap(rc.clone()) {
196                Ok(t) => Ok(unsafe { dst.put(t) }),
197                Err(_) => Err(TryIntoInnerError::Unavailable),
198            }
199        }
200
201        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
202            src_ptr: PtrConst<'src>,
203        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
204            let rc = unsafe { src_ptr.get::<alloc::rc::Rc<T>>() };
205            Ok(PtrConst::new(&**rc))
206        }
207
208        // Function to return inner type's shape
209        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
210            T::SHAPE
211        }
212
213        crate::Shape::builder()
214            .id(ConstTypeId::of::<Self>())
215            .layout(Layout::new::<Self>())
216            .type_params(&[crate::TypeParam {
217                name: "T",
218                shape: || T::SHAPE,
219            }])
220            .def(Def::SmartPointer(
221                SmartPointerDef::builder()
222                    .pointee(T::SHAPE)
223                    .flags(SmartPointerFlags::EMPTY)
224                    .known(KnownSmartPointer::Rc)
225                    .weak(|| <alloc::rc::Weak<T> as Facet>::SHAPE)
226                    .vtable(
227                        &const {
228                            SmartPointerVTable::builder()
229                                .borrow_fn(|this| {
230                                    let ptr = Self::as_ptr(unsafe { this.get() });
231                                    PtrConst::new(ptr)
232                                })
233                                .new_into_fn(|this, ptr| {
234                                    let t = unsafe { ptr.read::<T>() };
235                                    let rc = alloc::rc::Rc::new(t);
236                                    unsafe { this.put(rc) }
237                                })
238                                .downgrade_into_fn(|strong, weak| unsafe {
239                                    weak.put(alloc::rc::Rc::downgrade(strong.get::<Self>()))
240                                })
241                                .build()
242                        },
243                    )
244                    .build(),
245            ))
246            .vtable(
247                &const {
248                    let mut vtable =
249                        value_vtable_inner!(alloc::rc::Rc<T>, |f, _opts| write!(f, "Rc"));
250                    vtable.try_from_inner = Some(try_from_inner::<T>);
251                    vtable.try_into_inner = Some(try_into_inner::<T>);
252                    vtable.try_borrow_inner = Some(try_borrow_inner::<T>);
253                    vtable
254                },
255            )
256            .inner(inner_shape::<T>)
257            .build()
258    };
259}
260
261unsafe impl<'a, T: Facet<'a>> Facet<'a> for alloc::rc::Weak<T> {
262    const SHAPE: &'static crate::Shape = &const {
263        // Function to return inner type's shape
264        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
265            T::SHAPE
266        }
267
268        crate::Shape::builder()
269            .id(ConstTypeId::of::<Self>())
270            .layout(Layout::new::<Self>())
271            .type_params(&[crate::TypeParam {
272                name: "T",
273                shape: || T::SHAPE,
274            }])
275            .def(Def::SmartPointer(
276                SmartPointerDef::builder()
277                    .pointee(T::SHAPE)
278                    .flags(SmartPointerFlags::WEAK)
279                    .known(KnownSmartPointer::RcWeak)
280                    .strong(|| <alloc::rc::Rc<T> as Facet>::SHAPE)
281                    .vtable(
282                        &const {
283                            SmartPointerVTable::builder()
284                                .upgrade_into_fn(|weak, strong| unsafe {
285                                    Some(strong.put(weak.get::<Self>().upgrade()?))
286                                })
287                                .build()
288                        },
289                    )
290                    .build(),
291            ))
292            .vtable(&const { value_vtable_inner!(alloc::rc::Rc<T>, |f, _opts| write!(f, "Rc")) })
293            .inner(inner_shape::<T>)
294            .build()
295    };
296}
297
298unsafe impl<'a, T: 'a> Facet<'a> for Opaque<alloc::rc::Rc<T>> {
299    const SHAPE: &'static crate::Shape = &const {
300        crate::Shape::builder()
301            .id(ConstTypeId::of::<Self>())
302            .layout(Layout::new::<Self>())
303            .def(Def::SmartPointer(
304                SmartPointerDef::builder()
305                    .known(KnownSmartPointer::Rc)
306                    .vtable(
307                        &const {
308                            SmartPointerVTable::builder()
309                                .borrow_fn(|this| {
310                                    let ptr = alloc::rc::Rc::<T>::as_ptr(unsafe { this.get() });
311                                    PtrConst::new(ptr)
312                                })
313                                .new_into_fn(|this, ptr| {
314                                    let t = unsafe { ptr.read::<T>() };
315                                    let rc = alloc::rc::Rc::new(t);
316                                    unsafe { this.put(rc) }
317                                })
318                                .build()
319                        },
320                    )
321                    .build(),
322            ))
323            .vtable(value_vtable!(alloc::rc::Rc<T>, |f, _opts| write!(f, "Rc")))
324            .build()
325    };
326}
327
328#[cfg(test)]
329mod tests {
330    use alloc::rc::{Rc, Weak as RcWeak};
331    use alloc::string::String;
332    use alloc::sync::{Arc, Weak as ArcWeak};
333    use core::mem::MaybeUninit;
334
335    use super::*;
336
337    use crate::PtrUninit;
338
339    #[test]
340    fn test_arc_type_params() {
341        let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
342            panic!("Arc<T> should only have 1 type param")
343        };
344        assert_eq!(type_param_1.shape(), i32::SHAPE);
345    }
346
347    #[test]
348    fn test_arc_vtable() {
349        facet_testhelpers::setup();
350
351        let arc_shape = <Arc<String>>::SHAPE;
352        let arc_def = arc_shape
353            .def
354            .into_smart_pointer()
355            .expect("Arc<T> should have a smart pointer definition");
356
357        let weak_shape = <ArcWeak<String>>::SHAPE;
358        let weak_def = weak_shape
359            .def
360            .into_smart_pointer()
361            .expect("ArcWeak<T> should have a smart pointer definition");
362
363        // Keep this alive as long as the Arc inside it is used
364        let mut arc_storage = MaybeUninit::<Arc<String>>::zeroed();
365        let arc_ptr = unsafe {
366            let arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut arc_storage);
367
368            let value = String::from("example");
369            let value_ptr = PtrConst::new(&raw const value);
370
371            // SAFETY:
372            // - `arc_uninit_ptr` has layout Arc<String>
373            // - `value_ptr` is String
374            // - `value_ptr` is deallocated
375            let returned_ptr = arc_def
376                .vtable
377                .new_into_fn
378                .expect("Arc<T> should have new_into_fn vtable function")(
379                arc_uninit_ptr,
380                value_ptr,
381            );
382
383            // Don't run the destructor
384            core::mem::forget(value);
385
386            // Test correctness of the return value of new_into_fn
387            // SAFETY: Using correct type Arc<String>
388            assert_eq!(
389                returned_ptr.as_ptr(),
390                arc_uninit_ptr.as_byte_ptr() as *const Arc<String>
391            );
392
393            returned_ptr
394        };
395
396        unsafe {
397            // SAFETY: `arc_ptr` is valid
398            let borrowed = arc_def
399                .vtable
400                .borrow_fn
401                .expect("Arc<T> should have borrow_fn vtable function")(
402                arc_ptr.as_const()
403            );
404            assert_eq!(borrowed.get::<String>(), "example");
405        }
406
407        // Keep this alive as long as the RcWeak inside it is used
408        let mut new_arc_storage = MaybeUninit::<ArcWeak<String>>::zeroed();
409        let weak_ptr = unsafe {
410            let weak_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
411
412            let returned_ptr = arc_def
413                .vtable
414                .downgrade_into_fn
415                .expect("Arc<T> should have downgrade_into_fn vtable function")(
416                arc_ptr,
417                weak_uninit_ptr,
418            );
419
420            // Test correctness of the return value of downgrade_into_fn
421            // SAFETY: Using correct type ArcWeak<String>
422            assert_eq!(
423                returned_ptr.as_ptr(),
424                weak_uninit_ptr.as_byte_ptr() as *const ArcWeak<String>
425            );
426
427            returned_ptr
428        };
429
430        {
431            let mut new_arc_storage = MaybeUninit::<Arc<String>>::zeroed();
432            let new_arc_ptr = unsafe {
433                let new_arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
434
435                // SAFETY: `weak_ptr` is valid and `new_arc_uninit_ptr` has layout Weak<String>
436                let returned_ptr = weak_def
437                    .vtable
438                    .upgrade_into_fn
439                    .expect("ArcWeak<T> should have upgrade_into_fn vtable function")(
440                    weak_ptr,
441                    new_arc_uninit_ptr,
442                )
443                .expect("Upgrade should be successful");
444
445                // Test correctness of the return value of upgrade_into_fn
446                // SAFETY: Using correct type Arc<String>
447                assert_eq!(
448                    returned_ptr.as_ptr(),
449                    new_arc_uninit_ptr.as_byte_ptr() as *const Arc<String>
450                );
451
452                returned_ptr
453            };
454
455            unsafe {
456                // SAFETY: `new_arc_ptr` is valid
457                let borrowed = arc_def
458                    .vtable
459                    .borrow_fn
460                    .expect("Arc<T> should have borrow_fn vtable function")(
461                    new_arc_ptr.as_const()
462                );
463                assert_eq!(borrowed.get::<String>(), "example");
464            }
465
466            unsafe {
467                // SAFETY: Proper value at `arc_ptr`, which is not accessed after this
468                arc_shape
469                    .vtable
470                    .drop_in_place
471                    .expect("Arc<T> should have drop_in_place vtable function")(
472                    new_arc_ptr
473                );
474            }
475        }
476
477        unsafe {
478            // SAFETY: Proper value at `arc_ptr`, which is not accessed after this
479            arc_shape
480                .vtable
481                .drop_in_place
482                .expect("Arc<T> should have drop_in_place vtable function")(arc_ptr);
483        }
484
485        unsafe {
486            let mut new_arc_storage = MaybeUninit::<Arc<String>>::zeroed();
487            let new_arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
488
489            // SAFETY: `weak_ptr` is valid and `new_arc_uninit_ptr` has layout Weak<String>
490            if weak_def
491                .vtable
492                .upgrade_into_fn
493                .expect("ArcWeak<T> should have upgrade_into_fn vtable function")(
494                weak_ptr,
495                new_arc_uninit_ptr,
496            )
497            .is_some()
498            {
499                panic!("Upgrade should be unsuccessful")
500            }
501        };
502
503        unsafe {
504            // SAFETY: Proper value at `weak_ptr`, which is not accessed after this
505            weak_shape
506                .vtable
507                .drop_in_place
508                .expect("ArcWeak<T> should have drop_in_place vtable function")(
509                weak_ptr
510            );
511        }
512    }
513
514    #[test]
515    fn test_rc_type_params() {
516        let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
517            panic!("Rc<T> should only have 1 type param")
518        };
519        assert_eq!(type_param_1.shape(), i32::SHAPE);
520    }
521
522    #[test]
523    fn test_rc_vtable() {
524        facet_testhelpers::setup();
525
526        let rc_shape = <Rc<String>>::SHAPE;
527        let rc_def = rc_shape
528            .def
529            .into_smart_pointer()
530            .expect("Rc<T> should have a smart pointer definition");
531
532        let weak_shape = <RcWeak<String>>::SHAPE;
533        let weak_def = weak_shape
534            .def
535            .into_smart_pointer()
536            .expect("RcWeak<T> should have a smart pointer definition");
537
538        // Keep this alive as long as the Rc inside it is used
539        let mut rc_storage = MaybeUninit::<Rc<String>>::zeroed();
540        let rc_ptr = unsafe {
541            let rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut rc_storage);
542
543            let value = String::from("example");
544            let value_ptr = PtrConst::new(&raw const value);
545
546            // SAFETY:
547            // - `rc_uninit_ptr` has layout Rc<String>
548            // - `value_ptr` is String
549            // - `value_ptr` is deallocated after this without running the destructor
550            let returned_ptr = rc_def
551                .vtable
552                .new_into_fn
553                .expect("Rc<T> should have new_into_fn vtable function")(
554                rc_uninit_ptr, value_ptr
555            );
556
557            // Don't run the destructor
558            core::mem::forget(value);
559
560            // Test correctness of the return value of new_into_fn
561            // SAFETY: Using correct type Rc<String>
562            assert_eq!(
563                returned_ptr.as_ptr(),
564                rc_uninit_ptr.as_byte_ptr() as *const Rc<String>
565            );
566
567            returned_ptr
568        };
569
570        unsafe {
571            // SAFETY: `rc_ptr` is valid
572            let borrowed = rc_def
573                .vtable
574                .borrow_fn
575                .expect("Rc<T> should have borrow_fn vtable function")(
576                rc_ptr.as_const()
577            );
578            assert_eq!(borrowed.get::<String>(), "example");
579        }
580
581        // Keep this alive as long as the RcWeak inside it is used
582        let mut new_rc_storage = MaybeUninit::<RcWeak<String>>::zeroed();
583        let weak_ptr = unsafe {
584            let weak_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
585
586            let returned_ptr = rc_def
587                .vtable
588                .downgrade_into_fn
589                .expect("Rc<T> should have downgrade_into_fn vtable function")(
590                rc_ptr,
591                weak_uninit_ptr,
592            );
593
594            // Test correctness of the return value of downgrade_into_fn
595            // SAFETY: Using correct type RcWeak<String>
596            assert_eq!(
597                returned_ptr.as_ptr(),
598                weak_uninit_ptr.as_byte_ptr() as *const RcWeak<String>
599            );
600
601            returned_ptr
602        };
603
604        {
605            let mut new_rc_storage = MaybeUninit::<Rc<String>>::zeroed();
606            let new_rc_ptr = unsafe {
607                let new_rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
608
609                // SAFETY: `weak_ptr` is valid and `new_rc_uninit_ptr` has layout Weak<String>
610                let returned_ptr = weak_def
611                    .vtable
612                    .upgrade_into_fn
613                    .expect("RcWeak<T> should have upgrade_into_fn vtable function")(
614                    weak_ptr,
615                    new_rc_uninit_ptr,
616                )
617                .expect("Upgrade should be successful");
618
619                // Test correctness of the return value of upgrade_into_fn
620                // SAFETY: Using correct type Rc<String>
621                assert_eq!(
622                    returned_ptr.as_ptr(),
623                    new_rc_uninit_ptr.as_byte_ptr() as *const Rc<String>
624                );
625
626                returned_ptr
627            };
628
629            unsafe {
630                // SAFETY: `new_rc_ptr` is valid
631                let borrowed = rc_def
632                    .vtable
633                    .borrow_fn
634                    .expect("Rc<T> should have borrow_fn vtable function")(
635                    new_rc_ptr.as_const()
636                );
637                assert_eq!(borrowed.get::<String>(), "example");
638            }
639
640            unsafe {
641                // SAFETY: Proper value at `rc_ptr`, which is not accessed after this
642                rc_shape
643                    .vtable
644                    .drop_in_place
645                    .expect("Rc<T> should have drop_in_place vtable function")(
646                    new_rc_ptr
647                );
648            }
649        }
650
651        unsafe {
652            // SAFETY: Proper value at `rc_ptr`, which is not accessed after this
653            rc_shape
654                .vtable
655                .drop_in_place
656                .expect("Rc<T> should have drop_in_place vtable function")(rc_ptr);
657        }
658
659        unsafe {
660            let mut new_rc_storage = MaybeUninit::<Rc<String>>::zeroed();
661            let new_rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
662
663            // SAFETY: `weak_ptr` is valid and `new_rc_uninit_ptr` has layout Weak<String>
664            if weak_def
665                .vtable
666                .upgrade_into_fn
667                .expect("RcWeak<T> should have upgrade_into_fn vtable function")(
668                weak_ptr,
669                new_rc_uninit_ptr,
670            )
671            .is_some()
672            {
673                panic!("Upgrade should be unsuccessful")
674            }
675        };
676
677        unsafe {
678            // SAFETY: Proper value at `weak_ptr`, which is not accessed after this
679            weak_shape
680                .vtable
681                .drop_in_place
682                .expect("RcWeak<T> should have drop_in_place vtable function")(weak_ptr);
683        }
684    }
685}