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

facet-rs / facet / 15200164445

23 May 2025 01:21AM UTC coverage: 57.288% (+0.1%) from 57.185%
15200164445

Pull #666

github

web-flow
Merge 4232978c5 into 4b41e5c8a
Pull Request #666: Add indirection to vtable fns to fix cyclic types

715 of 1482 new or added lines in 34 files covered. (48.25%)

14 existing lines in 5 files now uncovered.

9747 of 17014 relevant lines covered (57.29%)

132.73 hits per line

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

67.68
/facet-core/src/impls_core/pointer.rs
1
use core::{fmt, hash::Hash, mem::transmute};
2

3
use crate::{
4
    CmpFn, CmpFnTyped, DebugFn, DebugFnTyped, DisplayFn, DisplayFnTyped, Facet, HashFn,
5
    HashFnTyped, HasherProxy, MarkerTraits, PartialEqFn, PartialEqFnTyped, PartialOrdFn,
6
    PartialOrdFnTyped, PointerType, Shape, Type, TypeParam, ValuePointerType, ValueVTable,
7
};
8

9
macro_rules! impl_facet_for_pointer {
10
    ($variant:ident: $type:ty => $shape:expr => $vtable_builder:expr => $ptr_type:ident, $mutable:expr) => {
11
        unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for $type {
12
            const VTABLE: &'static ValueVTable = &const {
13
                $vtable_builder
14
                    .type_name(|f, opts| {
34✔
15
                        if let Some(opts) = opts.for_children() {
34✔
16
                            if stringify!($ptr_type) == "Raw" {
34✔
17
                                if $mutable {
18
                                    write!(f, "*mut ")?;
2✔
19
                                } else {
20
                                    write!(f, "*const ")?;
6✔
21
                                }
22
                            } else {
23
                                write!(f, "&")?;
26✔
24
                                if $mutable {
25
                                    write!(f, "mut ")?;
4✔
26
                                }
22✔
27
                            }
28
                            (T::VTABLE.type_name)(f, opts)
34✔
29
                        } else {
30
                            if stringify!($ptr_type) == "Raw" {
×
31
                                if $mutable {
32
                                    write!(f, "*mut ⋯")
×
33
                                } else {
34
                                    write!(f, "*const ⋯")
×
35
                                }
36
                            } else {
37
                                write!(f, "&")?;
×
38
                                if $mutable {
39
                                    write!(f, "mut ⋯")
×
40
                                } else {
41
                                    write!(f, "⋯")
×
42
                                }
43
                            }
44
                        }
45
                    })
34✔
46
                    .build()
47
            };
48

49
            const SHAPE: &'static Shape<'static> = &const {
50
                $shape
51
                    .type_params(&[TypeParam {
52
                        name: "T",
53
                        shape: || T::SHAPE,
54
                    }])
55
                    .ty({
56
                        let is_wide =
57
                            ::core::mem::size_of::<$type>() != ::core::mem::size_of::<*const ()>();
58
                        let vpt = ValuePointerType {
59
                            mutable: $mutable,
60
                            wide: is_wide,
61
                            target: || T::SHAPE,
62
                        };
63

64
                        Type::Pointer(PointerType::$ptr_type(vpt))
65
                    })
66
                    .build()
67
            };
68
        }
69
    };
70
}
71

72
// *const pointers
73
impl_facet_for_pointer!(
74
    Raw: *const T
75
        => Shape::builder_for_sized::<Self>()
76
            .inner(|| T::SHAPE)
77
        => ValueVTable::builder::<Self>()
78
            .marker_traits(||
79
                MarkerTraits::EQ
80
                    .union(MarkerTraits::COPY)
6✔
81
                    .union(MarkerTraits::UNPIN),
6✔
82
            )
83
            .debug(|| Some(fmt::Debug::fmt))
36✔
NEW
84
            .clone_into(|| Some(|src, dst| unsafe { dst.put(*src) }))
×
85
            .eq(|| Some(|left, right| left.cast::<()>().eq(&right.cast::<()>())))
3✔
86
            .partial_ord(|| Some(|&left, &right| {
3✔
87
                left.cast::<()>().partial_cmp(&right.cast::<()>())
3✔
88
            }))
3✔
NEW
89
            .ord(|| Some(|&left, &right| left.cast::<()>().cmp(&right.cast::<()>())))
×
NEW
90
            .hash(|| Some(|value, hasher_this, hasher_write_fn| {
×
91
                value.hash(&mut unsafe {
×
92
                    HasherProxy::new(hasher_this, hasher_write_fn)
×
93
                })
×
NEW
94
            }))
×
95
        => Raw, false
96
);
97

98
// *mut pointers
99
impl_facet_for_pointer!(
100
    Raw: *mut T
101
        => Shape::builder_for_sized::<Self>()
102
            .inner(|| T::SHAPE)
103
        => ValueVTable::builder::<Self>()
104
            .marker_traits(||
105
                MarkerTraits::EQ
106
                    .union(MarkerTraits::COPY)
1✔
107
                    .union(MarkerTraits::UNPIN),
1✔
108
            )
109
            .debug(|| Some(fmt::Debug::fmt))
8✔
NEW
110
            .clone_into(|| Some(|src, dst| unsafe { dst.put(*src) }))
×
111
            .eq(|| Some(|left, right| left.cast::<()>().eq(&right.cast::<()>())))
1✔
112
            .partial_ord(|| Some(|&left, &right| {
1✔
113
                left.cast::<()>().partial_cmp(&right.cast::<()>())
1✔
114
            }))
1✔
NEW
115
            .ord(|| Some(|&left, &right| left.cast::<()>().cmp(&right.cast::<()>())))
×
NEW
116
            .hash(|| Some(|value, hasher_this, hasher_write_fn| {
×
117
                value.hash(&mut unsafe {
×
118
                    HasherProxy::new(hasher_this, hasher_write_fn)
×
119
                })
×
NEW
120
            }))
×
121
        => Raw, true
122
);
123

124
// &T references
125
impl_facet_for_pointer!(
126
    Reference: &'a T
127
        => Shape::builder_for_sized::<Self>()
128
        => {
129
            ValueVTable::builder::<Self>()
130
                .marker_traits(|| {
8✔
131
                    let mut marker_traits = MarkerTraits::COPY.union(MarkerTraits::UNPIN);
8✔
132
                    if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
8✔
133
                        marker_traits = marker_traits.union(MarkerTraits::EQ);
8✔
134
                    }
8✔
135
                    if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SYNC) {
8✔
136
                        marker_traits = marker_traits.union(MarkerTraits::SEND).union(MarkerTraits::SYNC);
7✔
137
                    }
7✔
138

139
                    marker_traits
8✔
140
                })
8✔
NEW
141
                .clone_into(|| Some(|src, dst| unsafe { dst.put(core::ptr::read(src)) }))
×
142
                .debug(|| {
80✔
143
                    if (T::VTABLE.debug)().is_some() {
80✔
144
                        Some(|value, f| {
48✔
145
                            let debug_fn = unsafe { transmute::<DebugFn, DebugFnTyped<T>>((T::VTABLE.debug)().unwrap()) };
48✔
146
                            debug_fn(*value, f)
48✔
147
                        })
48✔
148
                    } else {
NEW
149
                        None
×
150
                    }
151
                })
80✔
152
                .display(|| {
36✔
153
                    if (T::VTABLE.display)().is_some() {
36✔
154
                        Some(|value, f| {
20✔
155
                            let display_fn = unsafe { transmute::<DisplayFn, DisplayFnTyped<T>>((T::VTABLE.display)().unwrap()) };
20✔
156
                            display_fn(*value, f)
20✔
157
                        })
20✔
158
                    } else {
159
                        None
8✔
160
                    }
161
                })
36✔
162
                .eq(|| {
17✔
163
                    if (T::VTABLE.eq)().is_some() {
17✔
164
                        Some(|a, b| {
7✔
165
                            let eq_fn = unsafe { transmute::<PartialEqFn, PartialEqFnTyped<T>>((T::VTABLE.eq)().unwrap()) };
7✔
166
                            eq_fn(*a, *b)
7✔
167
                        })
7✔
168
                    } else {
NEW
169
                        None
×
170
                    }
171
                })
17✔
172
                .partial_ord(|| {
10✔
173
                    if (T::VTABLE.partial_ord)().is_some() {
10✔
174
                        Some(|a, b| {
7✔
175
                            let partial_ord_fn = unsafe { transmute::<PartialOrdFn, PartialOrdFnTyped<T>>((T::VTABLE.partial_ord)().unwrap()) };
7✔
176
                            partial_ord_fn(*a, *b)
7✔
177
                        })
7✔
178
                    } else {
NEW
179
                        None
×
180
                    }
181
                })
10✔
182
                .ord(|| {
7✔
183
                    if (T::VTABLE.ord)().is_some() {
7✔
NEW
184
                        Some(|a, b| {
×
NEW
185
                            let ord_fn = unsafe { transmute::<CmpFn, CmpFnTyped<T>>((T::VTABLE.ord)().unwrap()) };
×
NEW
186
                            ord_fn(*a, *b)
×
NEW
187
                        })
×
188
                    } else {
NEW
189
                        None
×
190
                    }
191
                })
7✔
NEW
192
                .hash(|| {
×
NEW
193
                    if (T::VTABLE.hash)().is_some() {
×
NEW
194
                        Some(|value, hasher_this, hasher_write_fn| {
×
NEW
195
                            let hash_fn = unsafe { transmute::<HashFn, HashFnTyped<T>>((T::VTABLE.hash)().unwrap()) };
×
NEW
196
                            hash_fn(*value, hasher_this, hasher_write_fn)
×
NEW
197
                        })
×
198
                    } else {
NEW
199
                        None
×
200
                    }
NEW
201
                })
×
202
        }
203
        => Reference, false
204
);
205

206
// &mut T references
207
impl_facet_for_pointer!(
208
    Reference: &'a mut T
209
        => Shape::builder_for_sized::<Self>()
210
        => {
211
            ValueVTable::builder::<Self>()
212
                .marker_traits(|| {
2✔
213
                    let mut marker_traits = MarkerTraits::UNPIN;
2✔
214
                    if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
2✔
215
                        marker_traits = marker_traits.union(MarkerTraits::EQ);
2✔
216
                    }
2✔
217
                    if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SEND) {
2✔
218
                        marker_traits = marker_traits.union(MarkerTraits::SEND);
1✔
219
                    }
1✔
220
                    if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SYNC) {
2✔
221
                        marker_traits = marker_traits.union(MarkerTraits::SYNC);
1✔
222
                    }
1✔
223

224
                    marker_traits
2✔
225
                })
2✔
226
                .debug(|| {
16✔
227
                    if (T::VTABLE.debug)().is_some() {
16✔
228
                        Some(|value, f| {
12✔
229
                            let debug_fn = unsafe { transmute::<DebugFn, DebugFnTyped<T>>((T::VTABLE.debug)().unwrap()) };
12✔
230
                            debug_fn(*value, f)
12✔
231
                        })
12✔
232
                    } else {
NEW
233
                        None
×
234
                    }
235
                })
16✔
236
                .display(|| {
12✔
237
                    if (T::VTABLE.display)().is_some() {
12✔
238
                        Some(|value, f| {
6✔
239
                            let display_fn = unsafe { transmute::<DisplayFn, DisplayFnTyped<T>>((T::VTABLE.display)().unwrap()) };
6✔
240
                            display_fn(*value, f)
6✔
241
                        })
6✔
242
                    } else {
243
                        None
4✔
244
                    }
245
                })
12✔
246
                .eq(|| {
4✔
247
                    if (T::VTABLE.eq)().is_some() {
4✔
248
                        Some(|a, b| {
2✔
249
                            let eq_fn = unsafe { transmute::<PartialEqFn, PartialEqFnTyped<T>>((T::VTABLE.eq)().unwrap()) };
2✔
250
                            eq_fn(*a, *b)
2✔
251
                        })
2✔
252
                    } else {
NEW
253
                        None
×
254
                    }
255
                })
4✔
256
                .partial_ord(|| {
2✔
257
                    if (T::VTABLE.partial_ord)().is_some() {
2✔
258
                        Some(|a, b| {
2✔
259
                            let partial_ord_fn = unsafe { transmute::<PartialOrdFn, PartialOrdFnTyped<T>>((T::VTABLE.partial_ord)().unwrap()) };
2✔
260
                            partial_ord_fn(*a, *b)
2✔
261
                        })
2✔
262
                    } else {
NEW
263
                        None
×
264
                    }
265
                })
2✔
266
                .ord(|| {
2✔
267
                    if (T::VTABLE.ord)().is_some() {
2✔
NEW
268
                        Some(|a, b| {
×
NEW
269
                            let ord_fn = unsafe { transmute::<CmpFn, CmpFnTyped<T>>((T::VTABLE.ord)().unwrap()) };
×
NEW
270
                            ord_fn(*a, *b)
×
NEW
271
                        })
×
272
                    } else {
NEW
273
                        None
×
274
                    }
275
                })
2✔
NEW
276
                .hash(|| {
×
NEW
277
                    if (T::VTABLE.hash)().is_some() {
×
NEW
278
                        Some(|value, hasher_this, hasher_write_fn| {
×
NEW
279
                            let hash_fn = unsafe { transmute::<HashFn, HashFnTyped<T>>((T::VTABLE.hash)().unwrap()) };
×
NEW
280
                            hash_fn(*value, hasher_this, hasher_write_fn)
×
NEW
281
                        })
×
282
                    } else {
NEW
283
                        None
×
284
                    }
NEW
285
                })
×
286
        }
287
        => Reference, true
288
);
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