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

facet-rs / facet / 16482665288

23 Jul 2025 09:56PM UTC coverage: 58.441% (-0.2%) from 58.68%
16482665288

Pull #855

github

web-flow
Merge 1ef12fa0a into 5e8e214d1
Pull Request #855: wip: Remove 'shape lifetime

399 of 571 new or added lines in 70 files covered. (69.88%)

3 existing lines in 3 files now uncovered.

11939 of 20429 relevant lines covered (58.44%)

120.56 hits per line

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

66.0
/facet-core/src/impls_alloc/boxed.rs
1
use alloc::boxed::Box;
2

3
use crate::{
4
    Def, Facet, KnownPointer, PointerDef, PointerFlags, PointerVTable, PtrConst, PtrConstWide,
5
    PtrMut, PtrUninit, Shape, TryBorrowInnerError, TryFromError, TryIntoInnerError, Type, UserType,
6
    ValueVTable, value_vtable,
7
};
8

9
unsafe impl<'a, T: Facet<'a>> Facet<'a> for Box<T> {
10
    const VTABLE: &'static ValueVTable = &const {
11
        // Define the functions for transparent conversion between Box<T> and T
NEW
12
        unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
×
13
            src_ptr: PtrConst<'src>,
×
NEW
14
            src_shape: &'static Shape,
×
15
            dst: PtrUninit<'dst>,
×
NEW
16
        ) -> Result<PtrMut<'dst>, TryFromError> {
×
17
            if src_shape.id != T::SHAPE.id {
×
18
                return Err(TryFromError::UnsupportedSourceShape {
×
19
                    src_shape,
×
20
                    expected: &[T::SHAPE],
×
21
                });
×
22
            }
×
23
            let t = unsafe { src_ptr.read::<T>() };
×
24
            let boxed = Box::new(t);
×
25
            Ok(unsafe { dst.put(boxed) })
×
26
        }
×
27

28
        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
29
            src_ptr: PtrMut<'src>,
×
30
            dst: PtrUninit<'dst>,
×
31
        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
32
            let boxed = unsafe { src_ptr.read::<Box<T>>() };
×
33
            Ok(unsafe { dst.put(*boxed) })
×
34
        }
×
35

36
        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
×
37
            src_ptr: PtrConst<'src>,
×
38
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
39
            let boxed = unsafe { src_ptr.get::<Box<T>>() };
×
40
            Ok(PtrConst::new(&**boxed))
×
41
        }
×
42

43
        let mut vtable = value_vtable!(alloc::boxed::Box<T>, |f, opts| {
51✔
44
            write!(f, "{}", Self::SHAPE.type_identifier)?;
51✔
45
            if let Some(opts) = opts.for_children() {
51✔
46
                write!(f, "<")?;
51✔
47
                (T::SHAPE.vtable.type_name())(f, opts)?;
51✔
48
                write!(f, ">")?;
51✔
49
            } else {
50
                write!(f, "<…>")?;
×
51
            }
52
            Ok(())
51✔
53
        });
51✔
54
        {
55
            let vtable = vtable.sized_mut().unwrap();
56
            vtable.try_from = || Some(try_from::<T>);
×
57
            vtable.try_into_inner = || Some(try_into_inner::<T>);
×
58
            vtable.try_borrow_inner = || Some(try_borrow_inner::<T>);
×
59
        }
60
        vtable
61
    };
62

63
    const SHAPE: &'static crate::Shape = &const {
64
        // Function to return inner type's shape
65
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
5✔
66
            T::SHAPE
5✔
67
        }
5✔
68

69
        crate::Shape::builder_for_sized::<Self>()
70
            .type_identifier("Box")
71
            .type_params(&[crate::TypeParam {
72
                name: "T",
73
                shape: || T::SHAPE,
74
            }])
75
            .ty(Type::User(UserType::Opaque))
76
            .def(Def::Pointer(
77
                PointerDef::builder()
78
                    .pointee(|| T::SHAPE)
79
                    .flags(PointerFlags::EMPTY)
80
                    .known(KnownPointer::Box)
81
                    .vtable(
82
                        &const {
83
                            PointerVTable::builder()
84
                                .borrow_fn(|this| unsafe {
85
                                    let concrete = this.get::<Box<T>>();
6✔
86
                                    let t: &T = concrete.as_ref();
6✔
87
                                    PtrConst::new(t as *const T).into()
6✔
88
                                })
6✔
89
                                .new_into_fn(|this, ptr| {
10✔
90
                                    let t = unsafe { ptr.read::<T>() };
10✔
91
                                    let boxed = Box::new(t);
10✔
92
                                    unsafe { this.put(boxed) }
10✔
93
                                })
10✔
94
                                .build()
95
                        },
96
                    )
97
                    .build(),
98
            ))
99
            .inner(inner_shape::<T>)
100
            .build()
101
    };
102
}
103

104
unsafe impl<'a> Facet<'a> for Box<str> {
105
    const VTABLE: &'static ValueVTable = &const {
106
        value_vtable!(alloc::boxed::Box<str>, |f, opts| {
8✔
107
            write!(f, "{}", Self::SHAPE.type_identifier)?;
8✔
108
            if let Some(opts) = opts.for_children() {
8✔
109
                write!(f, "<")?;
8✔
110
                (str::SHAPE.vtable.type_name())(f, opts)?;
8✔
111
                write!(f, ">")?;
8✔
112
            } else {
113
                write!(f, "<…>")?;
×
114
            }
115
            Ok(())
8✔
116
        })
8✔
117
    };
118

119
    const SHAPE: &'static crate::Shape = &const {
120
        fn inner_shape() -> &'static Shape {
2✔
121
            str::SHAPE
2✔
122
        }
2✔
123

124
        crate::Shape::builder_for_sized::<Self>()
125
            .type_identifier("Box")
126
            .type_params(&[crate::TypeParam {
127
                name: "T",
128
                shape: || str::SHAPE,
129
            }])
130
            .ty(Type::User(UserType::Opaque))
131
            .def(Def::Pointer(
132
                PointerDef::builder()
133
                    .pointee(|| str::SHAPE)
134
                    .flags(PointerFlags::EMPTY)
135
                    .known(KnownPointer::Box)
136
                    .vtable(
137
                        &const {
138
                            PointerVTable::builder()
139
                                .borrow_fn(|this| unsafe {
140
                                    let concrete = this.get::<Box<str>>();
1✔
141
                                    let s: &str = concrete;
1✔
142
                                    PtrConstWide::new(&raw const *s).into()
1✔
143
                                })
1✔
144
                                .new_into_fn(|_this, _ptr| todo!())
145
                                .build()
146
                        },
147
                    )
148
                    .build(),
149
            ))
150
            .inner(inner_shape)
151
            .build()
152
    };
153
}
154

155
#[cfg(test)]
156
mod tests {
157
    use alloc::boxed::Box;
158
    use alloc::string::String;
159

160
    use super::*;
161

162
    #[test]
163
    fn test_box_type_params() {
1✔
164
        let [type_param_1] = <Box<i32>>::SHAPE.type_params else {
1✔
165
            panic!("Box<T> should only have 1 type param")
×
166
        };
167
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
168
    }
1✔
169

170
    #[test]
171
    fn test_box_vtable_1_new_borrow_drop() -> eyre::Result<()> {
1✔
172
        facet_testhelpers::setup();
1✔
173

174
        let box_shape = <Box<String>>::SHAPE;
1✔
175
        let box_def = box_shape
1✔
176
            .def
1✔
177
            .into_pointer()
1✔
178
            .expect("Box<T> should have a smart pointer definition");
1✔
179

180
        // Allocate memory for the Box
181
        let box_uninit_ptr = box_shape.allocate()?;
1✔
182

183
        // Get the function pointer for creating a new Box from a value
184
        let new_into_fn = box_def
1✔
185
            .vtable
1✔
186
            .new_into_fn
1✔
187
            .expect("Box<T> should have new_into_fn");
1✔
188

189
        // Create the value and initialize the Box
190
        let mut value = String::from("example");
1✔
191
        let box_ptr = unsafe { new_into_fn(box_uninit_ptr, PtrMut::new(&raw mut value)) };
1✔
192
        // The value now belongs to the Box, prevent its drop
193
        core::mem::forget(value);
1✔
194

195
        // Get the function pointer for borrowing the inner value
196
        let borrow_fn = box_def
1✔
197
            .vtable
1✔
198
            .borrow_fn
1✔
199
            .expect("Box<T> should have borrow_fn");
1✔
200

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

206
        // Get the function pointer for dropping the Box
207
        let drop_fn = (box_shape.vtable.sized().unwrap().drop_in_place)()
1✔
208
            .expect("Box<T> should have drop_in_place");
1✔
209

210
        // Drop the Box in place
211
        // SAFETY: box_ptr points to a valid Box<String>
212
        unsafe { drop_fn(box_ptr) };
1✔
213

214
        // Deallocate the memory
215
        // SAFETY: box_ptr was allocated by box_shape and is now dropped (but memory is still valid)
216
        unsafe { box_shape.deallocate_mut(box_ptr)? };
1✔
217

218
        Ok(())
1✔
219
    }
1✔
220
}
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