• 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

73.75
/facet-core/src/impls_alloc/boxed.rs
1
use core::{alloc::Layout, ptr::NonNull};
2

3
use alloc::boxed::Box;
4

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

11
// Define the functions for transparent conversion between Box<T> and T
12
unsafe fn try_from<'src, 'dst>(
30✔
13
    src_ptr: PtrConst<'src>,
30✔
14
    src_shape: &'static Shape,
30✔
15
    dst: PtrUninit<'dst>,
30✔
16
) -> Result<PtrMut<'dst>, TryFromError> {
30✔
17
    let layout = src_shape.layout.sized_layout().unwrap();
30✔
18

19
    unsafe {
20
        let alloc = alloc::alloc::alloc(layout);
30✔
21
        if alloc.is_null() {
30✔
22
            alloc::alloc::handle_alloc_error(layout);
×
23
        }
30✔
24

25
        let src_ptr = src_ptr.as_ptr::<u8>();
30✔
26
        core::ptr::copy_nonoverlapping(src_ptr, alloc, layout.size());
30✔
27

28
        // layout of
29
        // Box<T> == *mut T == *mut u8
30
        Ok(dst.put(alloc))
30✔
31
    }
32
}
30✔
33

34
unsafe fn try_into_inner<'a, 'src, 'dst, T: ?Sized + Facet<'a>>(
×
35
    src_ptr: PtrMut<'src>,
×
36
    dst: PtrUninit<'dst>,
×
37
) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
38
    if const { size_of::<*const T>() == size_of::<*const ()>() } {
39
        let boxed = unsafe { src_ptr.read::<Box<T>>() };
×
40
        let layout = Layout::for_value(&*boxed);
×
41
        let ptr = Box::into_raw(boxed) as *mut u8;
×
42
        unsafe {
43
            core::ptr::copy_nonoverlapping(ptr, dst.as_mut_byte_ptr(), layout.size());
×
44
            alloc::alloc::dealloc(ptr, layout);
×
45
            Ok(dst.assume_init())
×
46
        }
47
    } else {
48
        panic!();
×
49
    }
50
}
×
51
unsafe impl<'a, T: ?Sized + Facet<'a>> Facet<'a> for Box<T> {
52
    const SHAPE: &'static crate::Shape = &const {
NEW
53
        unsafe fn try_borrow_inner<'a, 'src, T: ?Sized + Facet<'a>>(
×
NEW
54
            src_ptr: PtrConst<'src>,
×
NEW
55
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
NEW
56
            let boxed = unsafe { src_ptr.get::<Box<T>>() };
×
NEW
57
            Ok(PtrConst::new(NonNull::from(&**boxed)))
×
NEW
58
        }
×
59

60
        Shape {
61
            id: Shape::id_of::<Self>(),
62
            layout: Shape::layout_of::<Self>(),
63
            vtable: ValueVTable {
64
                type_name: |f, opts| {
37✔
65
                    write!(f, "{}", Self::SHAPE.type_identifier)?;
37✔
66
                    if let Some(opts) = opts.for_children() {
37✔
67
                        write!(f, "<")?;
37✔
68
                        (T::SHAPE.vtable.type_name())(f, opts)?;
37✔
69
                        write!(f, ">")?;
37✔
70
                    } else {
NEW
71
                        write!(f, "<…>")?;
×
72
                    }
73
                    Ok(())
37✔
74
                },
37✔
75
                try_from: if size_of::<*const T>() == size_of::<*const ()>() {
76
                    Some(try_from)
77
                } else {
78
                    None
79
                },
80
                try_into_inner: if size_of::<*const T>() == size_of::<*const ()>() {
81
                    Some(try_into_inner::<T>)
82
                } else {
83
                    None
84
                },
85
                try_borrow_inner: Some(try_borrow_inner::<T>),
86
                ..vtable_for_ptr::<T, Self>()
87
            },
88
            ty: Type::User(UserType::Opaque),
89
            def: Def::Pointer(PointerDef {
90
                vtable: &const {
91
                    PointerVTable {
92
                        borrow_fn: Some(|this| unsafe {
93
                            let concrete = this.get::<Box<T>>();
19✔
94
                            let t: &T = concrete.as_ref();
19✔
95
                            PtrConst::new(NonNull::from(t))
19✔
96
                        }),
19✔
97
                        new_into_fn: if size_of::<*const T>() == size_of::<*const ()>() {
98
                            Some(|this, ptr| unsafe {
99
                                try_from(ptr.as_const(), T::SHAPE, this).unwrap()
18✔
100
                            })
18✔
101
                        } else {
102
                            None
103
                        },
104
                        ..PointerVTable::new()
105
                    }
106
                },
107
                pointee: Some(T::SHAPE),
108
                weak: None,
109
                strong: None,
110
                flags: PointerFlags::EMPTY,
111
                known: Some(KnownPointer::Box),
112
            }),
113
            type_identifier: "Box",
114
            type_params: &[crate::TypeParam {
115
                name: "T",
116
                shape: T::SHAPE,
117
            }],
118
            doc: &[],
119
            attributes: &[],
120
            type_tag: None,
121
            inner: Some(T::SHAPE),
122
        }
123
    };
124
}
125

126
#[cfg(test)]
127
mod tests {
128
    use core::mem::ManuallyDrop;
129

130
    use alloc::boxed::Box;
131
    use alloc::string::String;
132

133
    use super::*;
134

135
    #[test]
136
    fn test_box_type_params() {
1✔
137
        let [type_param_1] = <Box<i32>>::SHAPE.type_params else {
1✔
138
            panic!("Box<T> should only have 1 type param")
×
139
        };
140
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
141
    }
1✔
142

143
    #[test]
144
    fn test_box_vtable_1_new_borrow_drop() {
1✔
145
        facet_testhelpers::setup();
1✔
146

147
        let box_shape = <Box<String>>::SHAPE;
1✔
148
        let box_def = box_shape
1✔
149
            .def
1✔
150
            .into_pointer()
1✔
151
            .expect("Box<T> should have a smart pointer definition");
1✔
152

153
        // Allocate memory for the Box
154
        let box_uninit_ptr = box_shape.allocate().unwrap();
1✔
155

156
        // Get the function pointer for creating a new Box from a value
157
        let new_into_fn = box_def
1✔
158
            .vtable
1✔
159
            .new_into_fn
1✔
160
            .expect("Box<T> should have new_into_fn");
1✔
161

162
        // Create the value and initialize the Box
163
        let mut value = ManuallyDrop::new(String::from("example"));
1✔
164
        let box_ptr =
1✔
165
            unsafe { new_into_fn(box_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
1✔
166
        // The value now belongs to the Box, prevent its drop
167

168
        // Get the function pointer for borrowing the inner value
169
        let borrow_fn = box_def
1✔
170
            .vtable
1✔
171
            .borrow_fn
1✔
172
            .expect("Box<T> should have borrow_fn");
1✔
173

174
        // Borrow the inner value and check it
175
        let borrowed_ptr = unsafe { borrow_fn(box_ptr.as_const()) };
1✔
176
        // SAFETY: borrowed_ptr points to a valid String within the Box
177
        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
1✔
178

179
        // Get the function pointer for dropping the Box
180
        let drop_fn = box_shape
1✔
181
            .vtable
1✔
182
            .drop_in_place
1✔
183
            .expect("Box<T> should have drop_in_place");
1✔
184

185
        // Drop the Box in place
186
        // SAFETY: box_ptr points to a valid Box<String>
187
        unsafe { drop_fn(box_ptr) };
1✔
188

189
        // Deallocate the memory
190
        // SAFETY: box_ptr was allocated by box_shape and is now dropped (but memory is still valid)
191
        unsafe { box_shape.deallocate_mut(box_ptr).unwrap() };
1✔
192
    }
1✔
193
}
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