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

facet-rs / facet / 19993677870

06 Dec 2025 08:12PM UTC coverage: 58.752% (+0.05%) from 58.705%
19993677870

push

github

fasterthanlime
Reduce/cordon bloat in facet, introduce bloatbench

Looks into codegen size, compile times etc. - again :) after adding a buuuunch of features.

- [x] Disable miette's default features (derive, which depends on syn) (`b.miette`)
- [x] Don't enable miette fancy by default in facet-json (`b.miette-fancy`)
- [x] Flatten closures in facet-json to avoid generic instantiations (`b.flatten-closures`)
- [x] Get rid of shape_of in Shape derive, use `#field_type` directly (`b.shape-of`)
- [x] Detect known derives in facet-macros, eschew impls! for them (`b.detect-derives`)
- [x] Gate nonzero impls, net impls (`b.gate-impls`)
- [x] Gate doc-comments, vtable-fmt, vtable-cmp, vtable-hash (`b.gate-vtable`)
- [x] Make 'auto trait detection' opt-in (`b.auto-traits-optin`)
- [x] Detect traits from `derive` and from `#[facet(default)]` (`b.derive-traits`)
- [x] Allow manual trait specification via `#[facet(traits(...))]` (`b.manual-traits`)
- [x] Go back to builders (they expand to less code) (`b.builders`)
- [x] VTable restructured with sub-vtables (`format`, `cmp`, `hash`, `markers`) (`b.vtable-substruct`)
- [x] Convert manual impls to ShapeBuilder (`scalar.rs`, `fn_ptr.rs`, `impls_num_complex.rs`) (`b.shapebuilder`)
- [x] **Confirmed**: `#![allow(uncommon_codepoints, nonstandard_style)]` in library = no warnings in consumers (`b.unicode-test`)
- [x] Add `FieldBuilder::new(name, shape_fn, offset)` builder (`b.field-builder`)
- [x] Add `StructTypeBuilder::new(kind, fields)` builder (`b.structtype-builder`)
- [x] Add `VariantBuilder::new(name, data)` builder (`b.variant-builder`)
- [x] Add `EnumTypeBuilder::new(enum_repr, variants)` builder (`b.enumtype-builder`)
- [x] Create `::facet::𝟋` module with type aliases and builder exports (`b.prelude-mod`)
- [x] Update derive macro to use builder pattern for Field, StructType, Variant, EnumType (`b.derive-builders`)

Based on analysis in `facet-bloatbench/MACRO-OPTIMIZATION-ANALYSIS.md`:

- [x] Remove `let mut vtable = const... (continued)

1199 of 3227 new or added lines in 72 files covered. (37.16%)

145 existing lines in 29 files now uncovered.

24253 of 41280 relevant lines covered (58.75%)

504.69 hits per line

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

67.31
/facet-core/src/impls_core/pointer.rs
1
use core::fmt;
2
use core::hash::Hash;
3

4
use crate::{
5
    CmpVTable, Def, Facet, FormatVTable, HashVTable, MarkerTraits, PointerType, Shape, Type,
6
    TypeParam, ValuePointerType, ValueVTable,
7
};
8

9
// *const pointers
10
unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *const T {
11
    const SHAPE: &'static Shape = &const {
12
        Shape {
13
            id: Shape::id_of::<Self>(),
14
            layout: Shape::layout_of::<Self>(),
15
            vtable: ValueVTable {
16
                type_name: |f, opts| {
12✔
17
                    if let Some(opts) = opts.for_children() {
12✔
18
                        write!(f, "*const ")?;
12✔
19
                        (T::SHAPE.vtable.type_name())(f, opts)
12✔
20
                    } else {
NEW
21
                        write!(f, "*const …")
×
22
                    }
23
                },
12✔
24
                drop_in_place: ValueVTable::drop_in_place_for::<Self>(),
25
                default_in_place: None,
26
                clone_into: Some(|src, dst| unsafe { dst.put(*src.get::<Self>()) }),
4✔
27
                parse: None,
28
                invariants: None,
29
                try_from: None,
30
                try_into_inner: None,
31
                try_borrow_inner: None,
32
                format: FormatVTable {
33
                    display: None,
34
                    debug: Some(|p, f| fmt::Debug::fmt(unsafe { p.get::<Self>() }, f)),
48✔
35
                },
36
                cmp: CmpVTable {
37
                    partial_eq: Some(|a, b| {
6✔
38
                        #[allow(ambiguous_wide_pointer_comparisons)]
39
                        unsafe {
40
                            *a.get::<Self>() == *b.get::<Self>()
6✔
41
                        }
42
                    }),
6✔
43
                    partial_ord: Some(|a, b| {
6✔
44
                        #[allow(ambiguous_wide_pointer_comparisons)]
45
                        unsafe {
46
                            a.get::<Self>().partial_cmp(b.get::<Self>())
6✔
47
                        }
48
                    }),
6✔
49
                    ord: Some(|a, b| {
6✔
50
                        #[allow(ambiguous_wide_pointer_comparisons)]
51
                        unsafe {
52
                            a.get::<Self>().cmp(b.get::<Self>())
6✔
53
                        }
54
                    }),
6✔
55
                },
56
                hash: HashVTable {
57
                    hash: Some(|value, hasher| unsafe {
NEW
58
                        value.get::<Self>().hash(&mut { hasher })
×
NEW
59
                    }),
×
60
                },
61
                markers: MarkerTraits::EMPTY.with_eq().with_copy(),
62
            },
63
            ty: {
64
                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
65
                let vpt = ValuePointerType {
66
                    mutable: false,
67
                    wide: is_wide,
68
                    target: T::SHAPE,
69
                };
70

71
                Type::Pointer(PointerType::Raw(vpt))
72
            },
73
            def: Def::Scalar,
74
            type_identifier: "*const _",
75
            type_params: &[TypeParam {
76
                name: "T",
77
                shape: T::SHAPE,
78
            }],
79
            doc: &[],
80
            attributes: &[],
81
            type_tag: None,
82
            inner: Some(T::SHAPE),
83
        }
84
    };
85
}
86

87
// *mut pointers
88
unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
89
    const SHAPE: &'static Shape = &const {
90
        Shape {
91
            id: Shape::id_of::<Self>(),
92
            layout: Shape::layout_of::<Self>(),
93
            vtable: ValueVTable {
94
                type_name: |f, opts| {
8✔
95
                    if let Some(opts) = opts.for_children() {
8✔
96
                        write!(f, "*mut ")?;
8✔
97
                        (T::SHAPE.vtable.type_name())(f, opts)
8✔
98
                    } else {
NEW
99
                        write!(f, "*mut …")
×
100
                    }
101
                },
8✔
102
                drop_in_place: ValueVTable::drop_in_place_for::<Self>(),
103
                default_in_place: None,
104
                clone_into: Some(|src, dst| unsafe { dst.put(*src.get::<Self>()) }),
4✔
105
                parse: None,
106
                invariants: None,
107
                try_from: None,
108
                try_into_inner: None,
109
                try_borrow_inner: None,
110
                format: FormatVTable {
111
                    display: None,
112
                    debug: Some(|p, f| fmt::Debug::fmt(unsafe { p.get::<Self>() }, f)),
32✔
113
                },
114
                cmp: CmpVTable {
115
                    partial_eq: Some(|a, b| {
4✔
116
                        #[allow(ambiguous_wide_pointer_comparisons)]
117
                        unsafe {
118
                            *a.get::<Self>() == *b.get::<Self>()
4✔
119
                        }
120
                    }),
4✔
121
                    partial_ord: Some(|a, b| {
4✔
122
                        #[allow(ambiguous_wide_pointer_comparisons)]
123
                        unsafe {
124
                            a.get::<Self>().partial_cmp(b.get::<Self>())
4✔
125
                        }
126
                    }),
4✔
127
                    ord: Some(|a, b| {
4✔
128
                        #[allow(ambiguous_wide_pointer_comparisons)]
129
                        unsafe {
130
                            a.get::<Self>().cmp(b.get::<Self>())
4✔
131
                        }
132
                    }),
4✔
133
                },
134
                hash: HashVTable {
135
                    hash: Some(|value, hasher| unsafe {
NEW
136
                        value.get::<Self>().hash(&mut { hasher })
×
NEW
137
                    }),
×
138
                },
139
                markers: MarkerTraits::EMPTY.with_eq().with_copy(),
140
            },
141
            ty: {
142
                let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
143
                let vpt = ValuePointerType {
144
                    mutable: true,
145
                    wide: is_wide,
146
                    target: T::SHAPE,
147
                };
148

149
                Type::Pointer(PointerType::Raw(vpt))
150
            },
151
            def: Def::Scalar,
152
            type_identifier: "*mut _",
153
            type_params: &[TypeParam {
154
                name: "T",
155
                shape: T::SHAPE,
156
            }],
157
            doc: &[],
158
            attributes: &[],
159
            type_tag: None,
160
            inner: Some(T::SHAPE),
161
        }
162
    };
163
}
164

165
#[cfg(test)]
166
mod test {
167
    use core::panic::{RefUnwindSafe, UnwindSafe};
168
    use impls::impls;
169

170
    #[allow(unused)]
171
    const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
×
172
    #[allow(unused)]
173
    const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
×
174

175
    #[allow(unused)]
176
    const fn ref_unwind_safe<T: RefUnwindSafe>() {
×
177
        assert_impls_unwind_safe::<&T>();
×
178
        assert_impls_ref_unwind_safe::<&T>();
×
179

180
        assert_impls_ref_unwind_safe::<&mut T>();
×
181

182
        assert_impls_unwind_safe::<*const T>();
×
183
        assert_impls_ref_unwind_safe::<*const T>();
×
184

185
        assert_impls_unwind_safe::<*mut T>();
×
186
        assert_impls_ref_unwind_safe::<*mut T>();
×
187
    }
×
188

189
    #[test]
190
    fn mut_ref_not_unwind_safe() {
1✔
191
        assert!(impls!(&mut (): !UnwindSafe));
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