• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 19992174439

06 Dec 2025 05:56PM UTC coverage: 58.742% (-0.005%) from 58.747%
19992174439

Pull #1118

github

web-flow
Merge d1d251ac8 into 45a8cb1c3
Pull Request #1118: Reduce/cordon bloat in facet, introduce bloatbench

1138 of 3103 new or added lines in 61 files covered. (36.67%)

540 existing lines in 30 files now uncovered.

24225 of 41240 relevant lines covered (58.74%)

502.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.55
/facet-core/src/impls_alloc/rc.rs
1
use core::ptr::NonNull;
2

3
use alloc::boxed::Box;
4
use alloc::rc::{Rc, Weak};
5
use alloc::vec::Vec;
6

7
use crate::shape_util::vtable_for_ptr;
8
use crate::{
9
    Def, Facet, KnownPointer, PointerDef, PointerFlags, PointerVTable, PtrConst, PtrMut, PtrUninit,
10
    Shape, ShapeBuilder, SliceBuilderVTable, TryBorrowInnerError, TryFromError, TryIntoInnerError,
11
    Type, UserType, ValueVTable,
12
};
13

14
unsafe impl<'a, T: Facet<'a>> Facet<'a> for Rc<T> {
15
    const SHAPE: &'static crate::Shape = &const {
16
        // Define the functions for transparent conversion between Rc<T> and T
17
        unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
1✔
18
            src_ptr: PtrConst<'src>,
1✔
19
            src_shape: &'static Shape,
1✔
20
            dst: PtrUninit<'dst>,
1✔
21
        ) -> Result<PtrMut<'dst>, TryFromError> {
1✔
22
            if src_shape.id != T::SHAPE.id {
1✔
NEW
23
                return Err(TryFromError::UnsupportedSourceShape {
×
NEW
24
                    src_shape,
×
NEW
25
                    expected: &[T::SHAPE],
×
NEW
26
                });
×
27
            }
1✔
28
            let t = unsafe { src_ptr.read::<T>() };
1✔
29
            let rc = Rc::new(t);
1✔
30
            Ok(unsafe { dst.put(rc) })
1✔
31
        }
1✔
32

NEW
33
        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
NEW
34
            src_ptr: PtrMut<'src>,
×
NEW
35
            dst: PtrUninit<'dst>,
×
NEW
36
        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
NEW
37
            let rc = unsafe { src_ptr.get::<Rc<T>>() };
×
NEW
38
            match Rc::try_unwrap(rc.clone()) {
×
NEW
39
                Ok(t) => Ok(unsafe { dst.put(t) }),
×
NEW
40
                Err(_) => Err(TryIntoInnerError::Unavailable),
×
41
            }
NEW
42
        }
×
43

NEW
44
        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
×
NEW
45
            src_ptr: PtrConst<'src>,
×
NEW
46
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
NEW
47
            let rc = unsafe { src_ptr.get::<Rc<T>>() };
×
NEW
48
            Ok(PtrConst::new(NonNull::from(&**rc)))
×
NEW
49
        }
×
50

51
        ShapeBuilder::for_sized::<Self>(
NEW
52
            |f, opts| {
×
NEW
53
                write!(f, "{}<", Self::SHAPE.type_identifier)?;
×
NEW
54
                if let Some(opts) = opts.for_children() {
×
NEW
55
                    (T::SHAPE.vtable.type_name())(f, opts)?;
×
56
                } else {
NEW
57
                    write!(f, "…")?;
×
58
                }
NEW
59
                write!(f, ">")?;
×
NEW
60
                Ok(())
×
NEW
61
            },
×
62
            "Rc",
63
        )
64
        .vtable(ValueVTable {
65
            type_name: |f, opts| {
1✔
66
                write!(f, "{}<", Self::SHAPE.type_identifier)?;
1✔
67
                if let Some(opts) = opts.for_children() {
1✔
68
                    (T::SHAPE.vtable.type_name())(f, opts)?;
1✔
69
                } else {
NEW
70
                    write!(f, "…")?;
×
71
                }
72
                write!(f, ">")?;
1✔
73
                Ok(())
1✔
74
            },
1✔
75
            try_from: Some(try_from::<T>),
76
            try_into_inner: Some(try_into_inner::<T>),
77
            try_borrow_inner: Some(try_borrow_inner::<T>),
78
            ..vtable_for_ptr::<T, Self>()
79
        })
80
        .ty(Type::User(UserType::Opaque))
81
        .def(Def::Pointer(PointerDef {
82
            vtable: &const {
83
                PointerVTable {
84
                    borrow_fn: Some(|this| {
3✔
85
                        let ptr = Self::as_ptr(unsafe { this.get() });
3✔
86
                        PtrConst::new(unsafe { NonNull::new_unchecked(ptr as *mut T) })
3✔
87
                    }),
3✔
88
                    new_into_fn: Some(|this, ptr| {
4✔
89
                        let t = unsafe { ptr.read::<T>() };
4✔
90
                        let rc = Rc::new(t);
4✔
91
                        unsafe { this.put(rc) }
4✔
92
                    }),
4✔
93
                    downgrade_into_fn: Some(|strong, weak| unsafe {
94
                        weak.put(Rc::downgrade(strong.get::<Self>()))
2✔
95
                    }),
2✔
96
                    ..PointerVTable::new()
97
                }
98
            },
99
            pointee: Some(T::SHAPE),
100
            weak: Some(|| <Weak<T> as Facet>::SHAPE),
101
            strong: None,
102
            flags: PointerFlags::EMPTY,
103
            known: Some(KnownPointer::Rc),
104
        }))
105
        .type_params(&[crate::TypeParam {
106
            name: "T",
107
            shape: T::SHAPE,
108
        }])
109
        .inner(T::SHAPE)
110
        .build()
111
    };
112
}
113

114
unsafe impl<'a> Facet<'a> for Rc<str> {
115
    const SHAPE: &'static crate::Shape = &const {
116
        ShapeBuilder::for_sized::<Self>(
NEW
117
            |f, opts| {
×
NEW
118
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
119
                if let Some(opts) = opts.for_children() {
×
NEW
120
                    write!(f, "<")?;
×
NEW
121
                    (str::SHAPE.vtable.type_name())(f, opts)?;
×
NEW
122
                    write!(f, ">")?;
×
123
                } else {
NEW
124
                    write!(f, "<…>")?;
×
125
                }
NEW
126
                Ok(())
×
NEW
127
            },
×
128
            "Rc",
129
        )
130
        .vtable(ValueVTable {
131
            type_name: |f, opts| {
2✔
132
                write!(f, "{}", Self::SHAPE.type_identifier)?;
2✔
133
                if let Some(opts) = opts.for_children() {
2✔
134
                    write!(f, "<")?;
2✔
135
                    (str::SHAPE.vtable.type_name())(f, opts)?;
2✔
136
                    write!(f, ">")?;
2✔
137
                } else {
NEW
138
                    write!(f, "<…>")?;
×
139
                }
140
                Ok(())
2✔
141
            },
2✔
142
            ..vtable_for_ptr::<str, Self>()
143
        })
144
        .ty(Type::User(UserType::Opaque))
145
        .def(Def::Pointer(PointerDef {
146
            vtable: &const {
147
                PointerVTable {
148
                    borrow_fn: Some(|this| unsafe {
149
                        let concrete = this.get::<Rc<str>>();
1✔
150
                        let s: &str = concrete;
1✔
151
                        PtrConst::new(NonNull::from(s))
1✔
152
                    }),
1✔
153
                    downgrade_into_fn: Some(|strong, weak| unsafe {
NEW
154
                        weak.put(Rc::downgrade(strong.get::<Self>()))
×
NEW
155
                    }),
×
156
                    ..PointerVTable::new()
157
                }
158
            },
159
            pointee: Some(str::SHAPE),
160
            weak: Some(|| <Weak<str> as Facet>::SHAPE),
161
            strong: None,
162
            flags: PointerFlags::EMPTY,
163
            known: Some(KnownPointer::Rc),
164
        }))
165
        .type_params(&[crate::TypeParam {
166
            name: "T",
167
            shape: str::SHAPE,
168
        }])
169
        .inner(str::SHAPE)
170
        .build()
171
    };
172
}
173

174
unsafe impl<'a, U: Facet<'a>> Facet<'a> for Rc<[U]> {
175
    const SHAPE: &'static crate::Shape = &const {
176
        fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut<'static> {
×
177
            let v = Box::new(Vec::<U>::new());
×
178
            let raw = Box::into_raw(v);
×
179
            PtrMut::new(unsafe { NonNull::new_unchecked(raw) })
×
180
        }
×
181

182
        fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
×
183
            unsafe {
×
184
                let vec = builder.as_mut::<Vec<U>>();
×
185
                let value = item.read::<U>();
×
186
                vec.push(value);
×
187
            }
×
188
        }
×
189

190
        fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut<'static>) -> PtrConst<'static> {
×
191
            unsafe {
192
                let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
×
193
                let arc: Rc<[U]> = (*vec_box).into();
×
194
                let arc_box = Box::new(arc);
×
195
                PtrConst::new(NonNull::new_unchecked(Box::into_raw(arc_box)))
×
196
            }
197
        }
×
198

199
        fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut<'static>) {
×
200
            unsafe {
×
201
                let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
×
202
            }
×
203
        }
×
204

205
        ShapeBuilder::for_sized::<Self>(
NEW
206
            |f, opts| {
×
NEW
207
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
208
                if let Some(opts) = opts.for_children() {
×
NEW
209
                    write!(f, "<")?;
×
NEW
210
                    (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
×
NEW
211
                    write!(f, ">")?;
×
212
                } else {
NEW
213
                    write!(f, "<…>")?;
×
214
                }
NEW
215
                Ok(())
×
NEW
216
            },
×
217
            "Rc",
218
        )
219
        .vtable(ValueVTable {
NEW
220
            type_name: |f, opts| {
×
NEW
221
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
222
                if let Some(opts) = opts.for_children() {
×
NEW
223
                    write!(f, "<")?;
×
NEW
224
                    (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
×
NEW
225
                    write!(f, ">")?;
×
226
                } else {
NEW
227
                    write!(f, "<…>")?;
×
228
                }
NEW
229
                Ok(())
×
NEW
230
            },
×
231
            ..vtable_for_ptr::<[U], Self>()
232
        })
233
        .ty(Type::User(UserType::Opaque))
234
        .def(Def::Pointer(PointerDef {
235
            vtable: &const {
236
                PointerVTable {
237
                    borrow_fn: Some(|this| unsafe {
NEW
238
                        let concrete = this.get::<Rc<[U]>>();
×
NEW
239
                        let s: &[U] = concrete;
×
NEW
240
                        PtrConst::new(NonNull::from(s))
×
NEW
241
                    }),
×
242
                    downgrade_into_fn: Some(|strong, weak| unsafe {
NEW
243
                        weak.put(Rc::downgrade(strong.get::<Self>()))
×
NEW
244
                    }),
×
245
                    slice_builder_vtable: Some(
246
                        &const {
247
                            SliceBuilderVTable::new(
248
                                slice_builder_new::<U>,
249
                                slice_builder_push::<U>,
250
                                slice_builder_convert::<U>,
251
                                slice_builder_free::<U>,
252
                            )
253
                        },
254
                    ),
255
                    ..PointerVTable::new()
256
                }
257
            },
258
            pointee: Some(<[U]>::SHAPE),
259
            weak: Some(|| <Weak<[U]> as Facet>::SHAPE),
260
            strong: None,
261
            flags: PointerFlags::EMPTY,
262
            known: Some(KnownPointer::Rc),
263
        }))
264
        .type_params(&[crate::TypeParam {
265
            name: "T",
266
            shape: <[U]>::SHAPE,
267
        }])
268
        .inner(<[U]>::SHAPE)
269
        .build()
270
    };
271
}
272

273
unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
274
    const SHAPE: &'static crate::Shape = &const {
275
        ShapeBuilder::for_sized::<Self>(
NEW
276
            |f, opts| {
×
NEW
277
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
278
                if let Some(opts) = opts.for_children() {
×
NEW
279
                    write!(f, "<")?;
×
NEW
280
                    T::SHAPE.vtable.type_name()(f, opts)?;
×
NEW
281
                    write!(f, ">")?;
×
282
                } else {
NEW
283
                    write!(f, "<…>")?;
×
284
                }
NEW
285
                Ok(())
×
NEW
286
            },
×
287
            "Weak",
288
        )
289
        .vtable(
290
            const {
291
                ValueVTable::builder(|f, opts| {
10✔
292
                    write!(f, "{}", Self::SHAPE.type_identifier)?;
10✔
293
                    if let Some(opts) = opts.for_children() {
10✔
294
                        write!(f, "<")?;
10✔
295
                        T::SHAPE.vtable.type_name()(f, opts)?;
10✔
296
                        write!(f, ">")?;
10✔
297
                    } else {
298
                        write!(f, "<…>")?;
×
299
                    }
300
                    Ok(())
10✔
301
                })
10✔
302
                .drop_in_place(ValueVTable::drop_in_place_for::<alloc::rc::Weak<T>>())
303
                .default_in_place(|target| unsafe { target.put(alloc::rc::Weak::<T>::new()) })
1✔
304
                .clone_into(|src, dst| unsafe { dst.put(src.get::<alloc::rc::Weak<T>>().clone()) })
1✔
305
                .debug(|_this, f| write!(f, "(Weak)"))
6✔
306
                .build()
307
            },
308
        )
309
        .ty(Type::User(UserType::Opaque))
310
        .def(Def::Pointer(PointerDef {
311
            vtable: &const {
312
                PointerVTable {
313
                    upgrade_into_fn: Some(|weak, strong| unsafe {
314
                        Some(strong.put(weak.get::<Self>().upgrade()?))
2✔
315
                    }),
2✔
316
                    ..PointerVTable::new()
317
                }
318
            },
319
            pointee: Some(T::SHAPE),
320
            weak: None,
321
            strong: Some(<Rc<T> as Facet>::SHAPE),
322
            flags: PointerFlags::WEAK,
323
            known: Some(KnownPointer::RcWeak),
324
        }))
325
        .type_params(&[crate::TypeParam {
326
            name: "T",
327
            shape: T::SHAPE,
328
        }])
329
        .inner(T::SHAPE)
330
        .build()
331
    };
332
}
333

334
unsafe impl<'a> Facet<'a> for Weak<str> {
335
    const SHAPE: &'static crate::Shape = &const {
336
        ShapeBuilder::for_sized::<Self>(
NEW
337
            |f, opts| {
×
NEW
338
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
339
                if let Some(opts) = opts.for_children() {
×
NEW
340
                    write!(f, "<")?;
×
NEW
341
                    (str::SHAPE.vtable.type_name())(f, opts)?;
×
NEW
342
                    write!(f, ">")?;
×
343
                } else {
NEW
344
                    write!(f, "<…>")?;
×
345
                }
NEW
346
                Ok(())
×
NEW
347
            },
×
348
            "Weak",
349
        )
350
        .vtable(
351
            const {
NEW
352
                ValueVTable::builder(|f, opts| {
×
353
                    write!(f, "{}", Self::SHAPE.type_identifier)?;
×
354
                    if let Some(opts) = opts.for_children() {
×
355
                        write!(f, "<")?;
×
356
                        (str::SHAPE.vtable.type_name())(f, opts)?;
×
357
                        write!(f, ">")?;
×
358
                    } else {
359
                        write!(f, "<…>")?;
×
360
                    }
361
                    Ok(())
×
362
                })
×
363
                .drop_in_place(ValueVTable::drop_in_place_for::<Self>())
364
                .clone_into(|src, dst| unsafe {
NEW
365
                    dst.put(src.get::<alloc::rc::Weak<str>>().clone())
×
NEW
366
                })
×
NEW
367
                .debug(|_this, f| write!(f, "(Weak)"))
×
368
                .build()
369
            },
370
        )
371
        .ty(Type::User(UserType::Opaque))
372
        .def(Def::Pointer(PointerDef {
373
            vtable: &const {
374
                PointerVTable {
375
                    upgrade_into_fn: Some(|weak, strong| unsafe {
NEW
376
                        Some(strong.put(weak.get::<Self>().upgrade()?))
×
NEW
377
                    }),
×
378
                    ..PointerVTable::new()
379
                }
380
            },
381
            pointee: Some(str::SHAPE),
382
            weak: None,
383
            strong: Some(<Rc<str> as Facet>::SHAPE),
384
            flags: PointerFlags::WEAK,
385
            known: Some(KnownPointer::RcWeak),
386
        }))
387
        .type_params(&[crate::TypeParam {
388
            name: "T",
389
            shape: str::SHAPE,
390
        }])
391
        .inner(str::SHAPE)
392
        .build()
393
    };
394
}
395

396
unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
397
    const SHAPE: &'static crate::Shape = &const {
398
        ShapeBuilder::for_sized::<Self>(
NEW
399
            |f, opts| {
×
NEW
400
                write!(f, "{}", Self::SHAPE.type_identifier)?;
×
NEW
401
                if let Some(opts) = opts.for_children() {
×
NEW
402
                    write!(f, "<")?;
×
NEW
403
                    (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
×
NEW
404
                    write!(f, ">")?;
×
405
                } else {
NEW
406
                    write!(f, "<…>")?;
×
407
                }
NEW
408
                Ok(())
×
NEW
409
            },
×
410
            "Weak",
411
        )
412
        .vtable(
413
            const {
NEW
414
                ValueVTable::builder(|f, opts| {
×
415
                    write!(f, "{}", Self::SHAPE.type_identifier)?;
×
416
                    if let Some(opts) = opts.for_children() {
×
417
                        write!(f, "<")?;
×
418
                        (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
×
419
                        write!(f, ">")?;
×
420
                    } else {
421
                        write!(f, "<…>")?;
×
422
                    }
423
                    Ok(())
×
424
                })
×
425
                .drop_in_place(ValueVTable::drop_in_place_for::<Self>())
426
                .clone_into(|src, dst| unsafe {
NEW
427
                    dst.put(src.get::<alloc::rc::Weak<[U]>>().clone())
×
NEW
428
                })
×
NEW
429
                .debug(|_this, f| write!(f, "(Weak)"))
×
430
                .build()
431
            },
432
        )
433
        .ty(Type::User(UserType::Opaque))
434
        .def(Def::Pointer(PointerDef {
435
            vtable: &const {
436
                PointerVTable {
437
                    upgrade_into_fn: Some(|weak, strong| unsafe {
NEW
438
                        Some(strong.put(weak.get::<Self>().upgrade()?))
×
NEW
439
                    }),
×
440
                    ..PointerVTable::new()
441
                }
442
            },
443
            pointee: Some(<[U]>::SHAPE),
444
            weak: None,
445
            strong: Some(<Rc<[U]> as Facet>::SHAPE),
446
            flags: PointerFlags::WEAK,
447
            known: Some(KnownPointer::RcWeak),
448
        }))
449
        .type_params(&[crate::TypeParam {
450
            name: "T",
451
            shape: <[U]>::SHAPE,
452
        }])
453
        .inner(<[U]>::SHAPE)
454
        .build()
455
    };
456
}
457

458
#[cfg(test)]
459
mod tests {
460
    use core::mem::ManuallyDrop;
461

462
    use alloc::rc::{Rc, Weak as RcWeak};
463
    use alloc::string::String;
464

465
    use super::*;
466

467
    #[test]
468
    fn test_rc_type_params() {
1✔
469
        let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
1✔
470
            panic!("Rc<T> should only have 1 type param")
×
471
        };
472
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
473
    }
1✔
474

475
    #[test]
476
    fn test_rc_vtable_1_new_borrow_drop() {
1✔
477
        facet_testhelpers::setup();
1✔
478

479
        let rc_shape = <Rc<String>>::SHAPE;
1✔
480
        let rc_def = rc_shape
1✔
481
            .def
1✔
482
            .into_pointer()
1✔
483
            .expect("Rc<T> should have a smart pointer definition");
1✔
484

485
        // Allocate memory for the Rc
486
        let rc_uninit_ptr = rc_shape.allocate().unwrap();
1✔
487

488
        // Get the function pointer for creating a new Rc from a value
489
        let new_into_fn = rc_def
1✔
490
            .vtable
1✔
491
            .new_into_fn
1✔
492
            .expect("Rc<T> should have new_into_fn");
1✔
493

494
        // Create the value and initialize the Rc
495
        let mut value = ManuallyDrop::new(String::from("example"));
1✔
496
        let rc_ptr = unsafe { new_into_fn(rc_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
1✔
497

498
        // Get the function pointer for borrowing the inner value
499
        let borrow_fn = rc_def
1✔
500
            .vtable
1✔
501
            .borrow_fn
1✔
502
            .expect("Rc<T> should have borrow_fn");
1✔
503

504
        // Borrow the inner value and check it
505
        let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
1✔
506
        // SAFETY: borrowed_ptr points to a valid String within the Rc
507
        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
1✔
508

509
        // Get the function pointer for dropping the Rc
510
        let drop_fn = rc_shape
1✔
511
            .vtable
1✔
512
            .drop_in_place
1✔
513
            .expect("Rc<T> should have drop_in_place");
1✔
514

515
        // Drop the Rc in place
516
        // SAFETY: rc_ptr points to a valid Rc<String>
517
        unsafe { drop_fn(rc_ptr) };
1✔
518

519
        // Deallocate the memory
520
        // SAFETY: rc_ptr was allocated by rc_shape and is now dropped (but memory is still valid)
521
        unsafe { rc_shape.deallocate_mut(rc_ptr).unwrap() };
1✔
522
    }
1✔
523

524
    #[test]
525
    fn test_rc_vtable_2_downgrade_upgrade_drop() {
1✔
526
        facet_testhelpers::setup();
1✔
527

528
        let rc_shape = <Rc<String>>::SHAPE;
1✔
529
        let rc_def = rc_shape
1✔
530
            .def
1✔
531
            .into_pointer()
1✔
532
            .expect("Rc<T> should have a smart pointer definition");
1✔
533

534
        let weak_shape = <RcWeak<String>>::SHAPE;
1✔
535
        let weak_def = weak_shape
1✔
536
            .def
1✔
537
            .into_pointer()
1✔
538
            .expect("RcWeak<T> should have a smart pointer definition");
1✔
539

540
        // 1. Create the first Rc (rc1)
541
        let rc1_uninit_ptr = rc_shape.allocate().unwrap();
1✔
542
        let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
1✔
543
        let mut value = ManuallyDrop::new(String::from("example"));
1✔
544
        let rc1_ptr =
1✔
545
            unsafe { new_into_fn(rc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
1✔
546

547
        // 2. Downgrade rc1 to create a weak pointer (weak1)
548
        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
1✔
549
        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
1✔
550
        // SAFETY: rc1_ptr points to a valid Rc, weak1_uninit_ptr is allocated for a Weak
551
        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
1✔
552

553
        // 3. Upgrade weak1 to create a second Rc (rc2)
554
        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
1✔
555
        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
1✔
556
        // SAFETY: weak1_ptr points to a valid Weak, rc2_uninit_ptr is allocated for an Rc.
557
        // Upgrade should succeed as rc1 still exists.
558
        let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
1✔
559
            .expect("Upgrade should succeed while original Rc exists");
1✔
560

561
        // Check the content of the upgraded Rc
562
        let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
1✔
563
        // SAFETY: rc2_ptr points to a valid Rc<String>
564
        let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
1✔
565
        // SAFETY: borrowed_ptr points to a valid String
566
        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
1✔
567

568
        // 4. Drop everything and free memory
569
        let rc_drop_fn = rc_shape.vtable.drop_in_place.unwrap();
1✔
570
        let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
1✔
571

572
        unsafe {
1✔
573
            // Drop Rcs
1✔
574
            rc_drop_fn(rc1_ptr);
1✔
575
            rc_shape.deallocate_mut(rc1_ptr).unwrap();
1✔
576
            rc_drop_fn(rc2_ptr);
1✔
577
            rc_shape.deallocate_mut(rc2_ptr).unwrap();
1✔
578

1✔
579
            // Drop Weak
1✔
580
            weak_drop_fn(weak1_ptr);
1✔
581
            weak_shape.deallocate_mut(weak1_ptr).unwrap();
1✔
582
        }
1✔
583
    }
1✔
584

585
    #[test]
586
    fn test_rc_vtable_3_downgrade_drop_try_upgrade() {
1✔
587
        facet_testhelpers::setup();
1✔
588

589
        let rc_shape = <Rc<String>>::SHAPE;
1✔
590
        let rc_def = rc_shape
1✔
591
            .def
1✔
592
            .into_pointer()
1✔
593
            .expect("Rc<T> should have a smart pointer definition");
1✔
594

595
        let weak_shape = <RcWeak<String>>::SHAPE;
1✔
596
        let weak_def = weak_shape
1✔
597
            .def
1✔
598
            .into_pointer()
1✔
599
            .expect("RcWeak<T> should have a smart pointer definition");
1✔
600

601
        // 1. Create the strong Rc (rc1)
602
        let rc1_uninit_ptr = rc_shape.allocate().unwrap();
1✔
603
        let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
1✔
604
        let mut value = ManuallyDrop::new(String::from("example"));
1✔
605
        let rc1_ptr =
1✔
606
            unsafe { new_into_fn(rc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
1✔
607

608
        // 2. Downgrade rc1 to create a weak pointer (weak1)
609
        let weak1_uninit_ptr = weak_shape.allocate().unwrap();
1✔
610
        let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
1✔
611
        // SAFETY: rc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
612
        let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
1✔
613

614
        // 3. Drop and free the strong pointer (rc1)
615
        let rc_drop_fn = rc_shape.vtable.drop_in_place.unwrap();
1✔
616
        unsafe {
1✔
617
            rc_drop_fn(rc1_ptr);
1✔
618
            rc_shape.deallocate_mut(rc1_ptr).unwrap();
1✔
619
        }
1✔
620

621
        // 4. Attempt to upgrade the weak pointer (weak1)
622
        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
1✔
623
        let rc2_uninit_ptr = rc_shape.allocate().unwrap();
1✔
624
        // SAFETY: weak1_ptr is valid (though points to dropped data), rc2_uninit_ptr is allocated for Rc
625
        let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
1✔
626

627
        // Assert that the upgrade failed
628
        assert!(
1✔
629
            upgrade_result.is_none(),
1✔
630
            "Upgrade should fail after the strong Rc is dropped"
631
        );
632

633
        // 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
634
        let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
1✔
635
        unsafe {
1✔
636
            // Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
1✔
637
            rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
1✔
638

1✔
639
            // Drop and deallocate the weak pointer
1✔
640
            weak_drop_fn(weak1_ptr);
1✔
641
            weak_shape.deallocate_mut(weak1_ptr).unwrap();
1✔
642
        }
1✔
643
    }
1✔
644
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc