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

facet-rs / facet / 14665423283

25 Apr 2025 01:11PM UTC coverage: 57.733% (-0.5%) from 58.213%
14665423283

Pull #390

github

web-flow
Merge 91f4b0118 into baf8b033b
Pull Request #390: 🧨 (big one) Introduce `Shape::inner` for (Utf8PathBuf, NonZero<u8> etc.) along with try_from_inner, try_into_inner, borrow_inner etc.

196 of 360 new or added lines in 17 files covered. (54.44%)

47 existing lines in 4 files now uncovered.

6559 of 11361 relevant lines covered (57.73%)

73.03 hits per line

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

79.87
/facet-core/src/impls_alloc/smartptr.rs
1
use core::alloc::Layout;
2

3
use 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

9
unsafe 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>>(
1✔
13
            src_ptr: PtrConst<'src>,
1✔
14
            src_shape: &'static Shape,
1✔
15
            dst: PtrUninit<'dst>,
1✔
16
        ) -> Result<PtrMut<'dst>, TryFromInnerError> {
1✔
17
            if src_shape.id != T::SHAPE.id {
1✔
NEW
18
                return Err(TryFromInnerError::UnsupportedSourceShape {
×
NEW
19
                    src_shape,
×
NEW
20
                    expected: &[T::SHAPE],
×
NEW
21
                });
×
22
            }
1✔
23
            let t = unsafe { src_ptr.read::<T>() };
1✔
24
            let arc = alloc::sync::Arc::new(t);
1✔
25
            Ok(unsafe { dst.put(arc) })
1✔
26
        }
1✔
27

NEW
28
        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
NEW
29
            src_ptr: PtrConst<'src>,
×
NEW
30
            dst: PtrUninit<'dst>,
×
NEW
31
        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
NEW
32
            let arc = unsafe { src_ptr.get::<alloc::sync::Arc<T>>() };
×
NEW
33
            match alloc::sync::Arc::try_unwrap(arc.clone()) {
×
NEW
34
                Ok(t) => Ok(unsafe { dst.put(t) }),
×
NEW
35
                Err(_) => Err(TryIntoInnerError::Unavailable),
×
36
            }
NEW
37
        }
×
38

NEW
39
        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
×
NEW
40
            src_ptr: PtrConst<'src>,
×
NEW
41
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
NEW
42
            let arc = unsafe { src_ptr.get::<alloc::sync::Arc<T>>() };
×
NEW
43
            Ok(PtrConst::new(&**arc))
×
NEW
44
        }
×
45

46
        // Function to return inner type's shape
47
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
2✔
48
            T::SHAPE
2✔
49
        }
2✔
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,
2✔
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| {
2✔
68
                                    let ptr = Self::as_ptr(unsafe { this.get() });
2✔
69
                                    PtrConst::new(ptr)
2✔
70
                                })
2✔
71
                                .new_into_fn(|this, ptr| {
1✔
72
                                    let t = unsafe { ptr.read::<T>() };
1✔
73
                                    let arc = alloc::sync::Arc::new(t);
1✔
74
                                    unsafe { this.put(arc) }
1✔
75
                                })
1✔
76
                                .downgrade_into_fn(|strong, weak| unsafe {
1✔
77
                                    weak.put(alloc::sync::Arc::downgrade(strong.get::<Self>()))
1✔
78
                                })
1✔
79
                                .build()
80
                        },
81
                    )
82
                    .build(),
83
            ))
84
            .vtable(
85
                &const {
86
                    let mut vtable =
NEW
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

99
unsafe 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
NEW
102
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
×
NEW
103
            T::SHAPE
×
NEW
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,
1✔
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 {
2✔
123
                                    Some(strong.put(weak.get::<Self>().upgrade()?))
2✔
124
                                })
2✔
125
                                .build()
126
                        },
127
                    )
128
                    .build(),
129
            ))
130
            .vtable(
NEW
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

138
unsafe 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")) },
1✔
166
            )
167
            .build()
168
    };
169
}
170

171
unsafe 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
NEW
174
        unsafe fn try_from_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
NEW
175
            src_ptr: PtrConst<'src>,
×
NEW
176
            src_shape: &'static Shape,
×
NEW
177
            dst: PtrUninit<'dst>,
×
NEW
178
        ) -> Result<PtrMut<'dst>, TryFromInnerError> {
×
NEW
179
            if src_shape.id != T::SHAPE.id {
×
NEW
180
                return Err(TryFromInnerError::UnsupportedSourceShape {
×
NEW
181
                    src_shape,
×
NEW
182
                    expected: &[T::SHAPE],
×
NEW
183
                });
×
NEW
184
            }
×
NEW
185
            let t = unsafe { src_ptr.read::<T>() };
×
NEW
186
            let rc = alloc::rc::Rc::new(t);
×
NEW
187
            Ok(unsafe { dst.put(rc) })
×
NEW
188
        }
×
189

NEW
190
        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
NEW
191
            src_ptr: PtrConst<'src>,
×
NEW
192
            dst: PtrUninit<'dst>,
×
NEW
193
        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
NEW
194
            let rc = unsafe { src_ptr.get::<alloc::rc::Rc<T>>() };
×
NEW
195
            match alloc::rc::Rc::try_unwrap(rc.clone()) {
×
NEW
196
                Ok(t) => Ok(unsafe { dst.put(t) }),
×
NEW
197
                Err(_) => Err(TryIntoInnerError::Unavailable),
×
198
            }
NEW
199
        }
×
200

NEW
201
        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
×
NEW
202
            src_ptr: PtrConst<'src>,
×
NEW
203
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
NEW
204
            let rc = unsafe { src_ptr.get::<alloc::rc::Rc<T>>() };
×
NEW
205
            Ok(PtrConst::new(&**rc))
×
NEW
206
        }
×
207

208
        // Function to return inner type's shape
NEW
209
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
×
NEW
210
            T::SHAPE
×
NEW
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,
1✔
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| {
2✔
230
                                    let ptr = Self::as_ptr(unsafe { this.get() });
2✔
231
                                    PtrConst::new(ptr)
2✔
232
                                })
2✔
233
                                .new_into_fn(|this, ptr| {
1✔
234
                                    let t = unsafe { ptr.read::<T>() };
1✔
235
                                    let rc = alloc::rc::Rc::new(t);
1✔
236
                                    unsafe { this.put(rc) }
1✔
237
                                })
1✔
238
                                .downgrade_into_fn(|strong, weak| unsafe {
1✔
239
                                    weak.put(alloc::rc::Rc::downgrade(strong.get::<Self>()))
1✔
240
                                })
1✔
241
                                .build()
242
                        },
243
                    )
244
                    .build(),
245
            ))
246
            .vtable(
247
                &const {
248
                    let mut vtable =
NEW
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

261
unsafe 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
NEW
264
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
×
NEW
265
            T::SHAPE
×
NEW
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 {
2✔
285
                                    Some(strong.put(weak.get::<Self>().upgrade()?))
2✔
286
                                })
2✔
287
                                .build()
288
                        },
289
                    )
290
                    .build(),
291
            ))
NEW
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

298
unsafe 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)]
329
mod 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() {
1✔
341
        let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
1✔
342
            panic!("Arc<T> should only have 1 type param")
×
343
        };
344
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
345
    }
1✔
346

347
    #[test]
348
    fn test_arc_vtable() {
1✔
349
        facet_testhelpers::setup();
1✔
350

1✔
351
        let arc_shape = <Arc<String>>::SHAPE;
1✔
352
        let arc_def = arc_shape
1✔
353
            .def
1✔
354
            .into_smart_pointer()
1✔
355
            .expect("Arc<T> should have a smart pointer definition");
1✔
356

1✔
357
        let weak_shape = <ArcWeak<String>>::SHAPE;
1✔
358
        let weak_def = weak_shape
1✔
359
            .def
1✔
360
            .into_smart_pointer()
1✔
361
            .expect("ArcWeak<T> should have a smart pointer definition");
1✔
362

1✔
363
        // Keep this alive as long as the Arc inside it is used
1✔
364
        let mut arc_storage = MaybeUninit::<Arc<String>>::zeroed();
1✔
365
        let arc_ptr = unsafe {
1✔
366
            let arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut arc_storage);
1✔
367

1✔
368
            let value = String::from("example");
1✔
369
            let value_ptr = PtrConst::new(&raw const value);
1✔
370

1✔
371
            // SAFETY:
1✔
372
            // - `arc_uninit_ptr` has layout Arc<String>
1✔
373
            // - `value_ptr` is String
1✔
374
            // - `value_ptr` is deallocated
1✔
375
            let returned_ptr = arc_def
1✔
376
                .vtable
1✔
377
                .new_into_fn
1✔
378
                .expect("Arc<T> should have new_into_fn vtable function")(
1✔
379
                arc_uninit_ptr,
1✔
380
                value_ptr,
1✔
381
            );
1✔
382

1✔
383
            // Don't run the destructor
1✔
384
            core::mem::forget(value);
1✔
385

1✔
386
            // Test correctness of the return value of new_into_fn
1✔
387
            // SAFETY: Using correct type Arc<String>
1✔
388
            assert_eq!(
1✔
389
                returned_ptr.as_ptr(),
1✔
390
                arc_uninit_ptr.as_byte_ptr() as *const Arc<String>
1✔
391
            );
392

393
            returned_ptr
1✔
394
        };
1✔
395

1✔
396
        unsafe {
1✔
397
            // SAFETY: `arc_ptr` is valid
1✔
398
            let borrowed = arc_def
1✔
399
                .vtable
1✔
400
                .borrow_fn
1✔
401
                .expect("Arc<T> should have borrow_fn vtable function")(
1✔
402
                arc_ptr.as_const()
1✔
403
            );
1✔
404
            assert_eq!(borrowed.get::<String>(), "example");
1✔
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();
1✔
409
        let weak_ptr = unsafe {
1✔
410
            let weak_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
1✔
411

1✔
412
            let returned_ptr = arc_def
1✔
413
                .vtable
1✔
414
                .downgrade_into_fn
1✔
415
                .expect("Arc<T> should have downgrade_into_fn vtable function")(
1✔
416
                arc_ptr,
1✔
417
                weak_uninit_ptr,
1✔
418
            );
1✔
419

1✔
420
            // Test correctness of the return value of downgrade_into_fn
1✔
421
            // SAFETY: Using correct type ArcWeak<String>
1✔
422
            assert_eq!(
1✔
423
                returned_ptr.as_ptr(),
1✔
424
                weak_uninit_ptr.as_byte_ptr() as *const ArcWeak<String>
1✔
425
            );
426

427
            returned_ptr
1✔
428
        };
1✔
429

1✔
430
        {
1✔
431
            let mut new_arc_storage = MaybeUninit::<Arc<String>>::zeroed();
1✔
432
            let new_arc_ptr = unsafe {
1✔
433
                let new_arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
1✔
434

1✔
435
                // SAFETY: `weak_ptr` is valid and `new_arc_uninit_ptr` has layout Weak<String>
1✔
436
                let returned_ptr = weak_def
1✔
437
                    .vtable
1✔
438
                    .upgrade_into_fn
1✔
439
                    .expect("ArcWeak<T> should have upgrade_into_fn vtable function")(
1✔
440
                    weak_ptr,
1✔
441
                    new_arc_uninit_ptr,
1✔
442
                )
1✔
443
                .expect("Upgrade should be successful");
1✔
444

1✔
445
                // Test correctness of the return value of upgrade_into_fn
1✔
446
                // SAFETY: Using correct type Arc<String>
1✔
447
                assert_eq!(
1✔
448
                    returned_ptr.as_ptr(),
1✔
449
                    new_arc_uninit_ptr.as_byte_ptr() as *const Arc<String>
1✔
450
                );
451

452
                returned_ptr
1✔
453
            };
1✔
454

1✔
455
            unsafe {
1✔
456
                // SAFETY: `new_arc_ptr` is valid
1✔
457
                let borrowed = arc_def
1✔
458
                    .vtable
1✔
459
                    .borrow_fn
1✔
460
                    .expect("Arc<T> should have borrow_fn vtable function")(
1✔
461
                    new_arc_ptr.as_const()
1✔
462
                );
1✔
463
                assert_eq!(borrowed.get::<String>(), "example");
1✔
464
            }
465

466
            unsafe {
1✔
467
                // SAFETY: Proper value at `arc_ptr`, which is not accessed after this
1✔
468
                arc_shape
1✔
469
                    .vtable
1✔
470
                    .drop_in_place
1✔
471
                    .expect("Arc<T> should have drop_in_place vtable function")(
1✔
472
                    new_arc_ptr
1✔
473
                );
1✔
474
            }
1✔
475
        }
1✔
476

1✔
477
        unsafe {
1✔
478
            // SAFETY: Proper value at `arc_ptr`, which is not accessed after this
1✔
479
            arc_shape
1✔
480
                .vtable
1✔
481
                .drop_in_place
1✔
482
                .expect("Arc<T> should have drop_in_place vtable function")(arc_ptr);
1✔
483
        }
1✔
484

1✔
485
        unsafe {
1✔
486
            let mut new_arc_storage = MaybeUninit::<Arc<String>>::zeroed();
1✔
487
            let new_arc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_arc_storage);
1✔
488

1✔
489
            // SAFETY: `weak_ptr` is valid and `new_arc_uninit_ptr` has layout Weak<String>
1✔
490
            if weak_def
1✔
491
                .vtable
1✔
492
                .upgrade_into_fn
1✔
493
                .expect("ArcWeak<T> should have upgrade_into_fn vtable function")(
1✔
494
                weak_ptr,
1✔
495
                new_arc_uninit_ptr,
1✔
496
            )
1✔
497
            .is_some()
1✔
498
            {
499
                panic!("Upgrade should be unsuccessful")
×
500
            }
1✔
501
        };
1✔
502

1✔
503
        unsafe {
1✔
504
            // SAFETY: Proper value at `weak_ptr`, which is not accessed after this
1✔
505
            weak_shape
1✔
506
                .vtable
1✔
507
                .drop_in_place
1✔
508
                .expect("ArcWeak<T> should have drop_in_place vtable function")(
1✔
509
                weak_ptr
1✔
510
            );
1✔
511
        }
1✔
512
    }
1✔
513

514
    #[test]
515
    fn test_rc_type_params() {
1✔
516
        let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
1✔
517
            panic!("Rc<T> should only have 1 type param")
×
518
        };
519
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
520
    }
1✔
521

522
    #[test]
523
    fn test_rc_vtable() {
1✔
524
        facet_testhelpers::setup();
1✔
525

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

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

1✔
538
        // Keep this alive as long as the Rc inside it is used
1✔
539
        let mut rc_storage = MaybeUninit::<Rc<String>>::zeroed();
1✔
540
        let rc_ptr = unsafe {
1✔
541
            let rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut rc_storage);
1✔
542

1✔
543
            let value = String::from("example");
1✔
544
            let value_ptr = PtrConst::new(&raw const value);
1✔
545

1✔
546
            // SAFETY:
1✔
547
            // - `rc_uninit_ptr` has layout Rc<String>
1✔
548
            // - `value_ptr` is String
1✔
549
            // - `value_ptr` is deallocated after this without running the destructor
1✔
550
            let returned_ptr = rc_def
1✔
551
                .vtable
1✔
552
                .new_into_fn
1✔
553
                .expect("Rc<T> should have new_into_fn vtable function")(
1✔
554
                rc_uninit_ptr, value_ptr
1✔
555
            );
1✔
556

1✔
557
            // Don't run the destructor
1✔
558
            core::mem::forget(value);
1✔
559

1✔
560
            // Test correctness of the return value of new_into_fn
1✔
561
            // SAFETY: Using correct type Rc<String>
1✔
562
            assert_eq!(
1✔
563
                returned_ptr.as_ptr(),
1✔
564
                rc_uninit_ptr.as_byte_ptr() as *const Rc<String>
1✔
565
            );
566

567
            returned_ptr
1✔
568
        };
1✔
569

1✔
570
        unsafe {
1✔
571
            // SAFETY: `rc_ptr` is valid
1✔
572
            let borrowed = rc_def
1✔
573
                .vtable
1✔
574
                .borrow_fn
1✔
575
                .expect("Rc<T> should have borrow_fn vtable function")(
1✔
576
                rc_ptr.as_const()
1✔
577
            );
1✔
578
            assert_eq!(borrowed.get::<String>(), "example");
1✔
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();
1✔
583
        let weak_ptr = unsafe {
1✔
584
            let weak_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
1✔
585

1✔
586
            let returned_ptr = rc_def
1✔
587
                .vtable
1✔
588
                .downgrade_into_fn
1✔
589
                .expect("Rc<T> should have downgrade_into_fn vtable function")(
1✔
590
                rc_ptr,
1✔
591
                weak_uninit_ptr,
1✔
592
            );
1✔
593

1✔
594
            // Test correctness of the return value of downgrade_into_fn
1✔
595
            // SAFETY: Using correct type RcWeak<String>
1✔
596
            assert_eq!(
1✔
597
                returned_ptr.as_ptr(),
1✔
598
                weak_uninit_ptr.as_byte_ptr() as *const RcWeak<String>
1✔
599
            );
600

601
            returned_ptr
1✔
602
        };
1✔
603

1✔
604
        {
1✔
605
            let mut new_rc_storage = MaybeUninit::<Rc<String>>::zeroed();
1✔
606
            let new_rc_ptr = unsafe {
1✔
607
                let new_rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
1✔
608

1✔
609
                // SAFETY: `weak_ptr` is valid and `new_rc_uninit_ptr` has layout Weak<String>
1✔
610
                let returned_ptr = weak_def
1✔
611
                    .vtable
1✔
612
                    .upgrade_into_fn
1✔
613
                    .expect("RcWeak<T> should have upgrade_into_fn vtable function")(
1✔
614
                    weak_ptr,
1✔
615
                    new_rc_uninit_ptr,
1✔
616
                )
1✔
617
                .expect("Upgrade should be successful");
1✔
618

1✔
619
                // Test correctness of the return value of upgrade_into_fn
1✔
620
                // SAFETY: Using correct type Rc<String>
1✔
621
                assert_eq!(
1✔
622
                    returned_ptr.as_ptr(),
1✔
623
                    new_rc_uninit_ptr.as_byte_ptr() as *const Rc<String>
1✔
624
                );
625

626
                returned_ptr
1✔
627
            };
1✔
628

1✔
629
            unsafe {
1✔
630
                // SAFETY: `new_rc_ptr` is valid
1✔
631
                let borrowed = rc_def
1✔
632
                    .vtable
1✔
633
                    .borrow_fn
1✔
634
                    .expect("Rc<T> should have borrow_fn vtable function")(
1✔
635
                    new_rc_ptr.as_const()
1✔
636
                );
1✔
637
                assert_eq!(borrowed.get::<String>(), "example");
1✔
638
            }
639

640
            unsafe {
1✔
641
                // SAFETY: Proper value at `rc_ptr`, which is not accessed after this
1✔
642
                rc_shape
1✔
643
                    .vtable
1✔
644
                    .drop_in_place
1✔
645
                    .expect("Rc<T> should have drop_in_place vtable function")(
1✔
646
                    new_rc_ptr
1✔
647
                );
1✔
648
            }
1✔
649
        }
1✔
650

1✔
651
        unsafe {
1✔
652
            // SAFETY: Proper value at `rc_ptr`, which is not accessed after this
1✔
653
            rc_shape
1✔
654
                .vtable
1✔
655
                .drop_in_place
1✔
656
                .expect("Rc<T> should have drop_in_place vtable function")(rc_ptr);
1✔
657
        }
1✔
658

1✔
659
        unsafe {
1✔
660
            let mut new_rc_storage = MaybeUninit::<Rc<String>>::zeroed();
1✔
661
            let new_rc_uninit_ptr = PtrUninit::from_maybe_uninit(&mut new_rc_storage);
1✔
662

1✔
663
            // SAFETY: `weak_ptr` is valid and `new_rc_uninit_ptr` has layout Weak<String>
1✔
664
            if weak_def
1✔
665
                .vtable
1✔
666
                .upgrade_into_fn
1✔
667
                .expect("RcWeak<T> should have upgrade_into_fn vtable function")(
1✔
668
                weak_ptr,
1✔
669
                new_rc_uninit_ptr,
1✔
670
            )
1✔
671
            .is_some()
1✔
672
            {
673
                panic!("Upgrade should be unsuccessful")
×
674
            }
1✔
675
        };
1✔
676

1✔
677
        unsafe {
1✔
678
            // SAFETY: Proper value at `weak_ptr`, which is not accessed after this
1✔
679
            weak_shape
1✔
680
                .vtable
1✔
681
                .drop_in_place
1✔
682
                .expect("RcWeak<T> should have drop_in_place vtable function")(weak_ptr);
1✔
683
        }
1✔
684
    }
1✔
685
}
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

© 2025 Coveralls, Inc