• 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

19.28
/facet-core/src/impls_core/tuple.rs
1
use core::{cmp::Ordering, fmt, mem};
2

3
use crate::{
4
    Characteristic, Facet, MarkerTraits, SequenceType, Shape, TupleType, Type, TypeNameOpts,
5
    VTableView, ValueVTable, types::field_in_type,
6
};
7

8
#[inline(always)]
9
pub fn write_type_name_list(
×
10
    f: &mut fmt::Formatter<'_>,
×
11
    opts: TypeNameOpts,
×
12
    open: &'static str,
×
13
    delimiter: &'static str,
×
14
    close: &'static str,
×
15
    shapes: &'static [&'static Shape],
×
16
) -> fmt::Result {
×
17
    f.pad(open)?;
×
18
    if let Some(opts) = opts.for_children() {
×
19
        for (index, shape) in shapes.iter().enumerate() {
×
20
            if index > 0 {
×
21
                f.pad(delimiter)?;
×
22
            }
×
23
            shape.write_type_name(f, opts)?;
×
24
        }
25
    } else {
26
        write!(f, "⋯")?;
×
27
    }
28
    f.pad(close)?;
×
29
    Ok(())
×
30
}
×
31

32
macro_rules! impl_facet_for_tuple {
33
    // Used to implement the next bigger tuple type, by taking the next typename & associated index
34
    // out of `remaining`, if it exists.
35
    {
36
        continue from ($($elems:ident.$idx:tt,)+),
37
        remaining ()
38
    } => {};
39
    {
40
        continue from ($($elems:ident.$idx:tt,)+),
41
        remaining ($next:ident.$nextidx:tt, $($remaining:ident.$remainingidx:tt,)*)
42
    } => {
43
        impl_facet_for_tuple! {
44
            impl ($($elems.$idx,)+ $next.$nextidx,),
45
            remaining ($($remaining.$remainingidx,)*)
46
        }
47
    };
48
    // Handle commas correctly for the debug implementation
49
    { debug on $f:ident { $first:stmt; } } => {
50
        write!($f, "(")?;
51
        $first
52
        write!($f, ",)")
53
    };
54
    { debug on $f:ident { $first:stmt; $($stmt:stmt;)+ } } => {
55
        write!($f, "(")?;
56
        $first
57
        $(
58
            write!($f, ", ")?;
59
            $stmt
60
        )+
61
        write!($f, ")")
62
    };
63
    // Common structure of eq, partial_ord & ord
64
    { ord on ($($elems:ident.$idx:tt,)+), $cmp:ident($a:ident, $b:ident), eq = $eq:expr } => {{
65
        $(
66
            unsafe {
67
                let ordering = (<VTableView<$elems>>::of().$cmp().unwrap_unchecked())(
68
                    &$a.$idx,
69
                    &$b.$idx,
70
                );
71

72
                if ordering != $eq {
73
                    return ordering;
74
                }
75
            }
76
        )+
77

78
        $eq
79
    }};
80
    // Actually generate the trait implementation, and keep the remaining possible elements around
81
    {
82
        impl ($($elems:ident.$idx:tt,)+),
83
        remaining ($($remaining:ident.$remainingidx:tt,)*)
84
    } => {
85
        unsafe impl<'a $(, $elems)+> Facet<'a> for ($($elems,)+)
86
        where
87
            $($elems: Facet<'a>,)+
88
        {
89
            const VTABLE: &'static ValueVTable = &const {
90
                ValueVTable::builder::<Self>()
91
                    .type_name(|f, opts| {
453✔
92
                        write_type_name_list(f, opts, "(", ", ", ")", &[$($elems::SHAPE),+])
453✔
93
                    })
453✔
94
                    .drop_in_place(|| Some(|data| unsafe { data.drop_in_place::<Self>() }))
10✔
95
                    .marker_traits(||
UNCOV
96
                        MarkerTraits::all()
×
NEW
97
                            $(.intersection($elems::SHAPE.vtable.marker_traits()))+
×
98
                    )
NEW
99
                    .debug(|| {
×
NEW
100
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
×
NEW
101
                        if Characteristic::Debug.all(elem_shapes) {
×
NEW
102
                            Some(|value, f| {
×
NEW
103
                                impl_facet_for_tuple! {
×
104
                                    debug on f {
105
                                        $(
NEW
106
                                            (<VTableView<$elems>>::of().debug().unwrap())(
×
NEW
107
                                                &value.$idx,
×
NEW
108
                                                f,
×
NEW
109
                                            )?;
×
110
                                        )+
111
                                    }
112
                                }
NEW
113
                            })
×
114
                        } else {
NEW
115
                            None
×
116
                        }
NEW
117
                    })
×
118
                    .default_in_place(|| {
96✔
119
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
96✔
120
                        if Characteristic::all_default(elem_shapes) {
96✔
121
                            Some(|mut dst| {
70✔
122
                                $(
123
                                    unsafe {
70✔
124
                                        (<VTableView<$elems>>::of().default_in_place().unwrap())(
70✔
125
                                            dst.field_uninit_at(mem::offset_of!(Self, $idx))
70✔
126
                                        );
70✔
127
                                    }
70✔
128
                                )+
129

130
                                unsafe { dst.assume_init() }
70✔
131
                            })
70✔
132
                        } else {
NEW
133
                            None
×
134
                        }
135
                    })
96✔
136
                    // .clone_into(|| {
137
                    //     let elem_shapes = const { &[$($elems::SHAPE),+] };
138
                    //     if Characteristic::Clone.all(elem_shapes) {
139
                    //         Some(|src, dst| {
140
                    //             $({
141
                    //                 let offset = mem::offset_of!(Self, $idx);
142
                    //                 unsafe {
143
                    //                     (<VTableView<$elems>>::of().clone_into().unwrap())(
144
                    //                         src.field(offset),
145
                    //                         dst.field_uninit_at(offset),
146
                    //                     );
147
                    //                 }
148
                    //             })+
149

150
                    //             unsafe { dst.assume_init() }
151
                    //         })
152
                    //     } else {
153
                    //         None
154
                    //     }
155
                    // })
NEW
156
                    .eq(|| {
×
NEW
157
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
×
NEW
158
                        if Characteristic::all_partial_eq(elem_shapes) {
×
159
                            Some(|a, b| impl_facet_for_tuple! {
160
                                ord on ($($elems.$idx,)+),
161
                                eq(a, b),
NEW
162
                                eq = true
×
NEW
163
                            })
×
164
                        } else {
NEW
165
                            None
×
166
                        }
NEW
167
                    })
×
NEW
168
                    .partial_ord(|| {
×
NEW
169
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
×
NEW
170
                        if Characteristic::all_partial_ord(elem_shapes) {
×
171
                            Some(|a, b| impl_facet_for_tuple! {
172
                                ord on ($($elems.$idx,)+),
173
                                partial_ord(a, b),
NEW
174
                                eq = Some(Ordering::Equal)
×
NEW
175
                            })
×
176
                        } else {
NEW
177
                            None
×
178
                        }
NEW
179
                    })
×
NEW
180
                    .ord(|| {
×
NEW
181
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
×
NEW
182
                        if Characteristic::all_ord(elem_shapes) {
×
183
                            Some(|a, b| impl_facet_for_tuple! {
184
                                ord on ($($elems.$idx,)+),
185
                                ord(a, b),
NEW
186
                                eq = Ordering::Equal
×
NEW
187
                            })
×
188
                        } else {
NEW
189
                            None
×
190
                        }
NEW
191
                    })
×
NEW
192
                    .hash(|| {
×
NEW
193
                        let elem_shapes = const { &[$($elems::SHAPE),+] };
×
NEW
194
                        if Characteristic::all_hash(elem_shapes) {
×
NEW
195
                            Some(|value, hasher_this, hasher_write_fn| {
×
196
                                $(
NEW
197
                                    (<VTableView<$elems>>::of().hash().unwrap())(
×
198
                                        &value.$idx,
×
NEW
199
                                        hasher_this,
×
NEW
200
                                        hasher_write_fn,
×
NEW
201
                                    );
×
202
                                )+
NEW
203
                            })
×
204
                        } else {
NEW
205
                            None
×
206
                        }
NEW
207
                    })
×
208
                    .build()
209
            };
210

211
            const SHAPE: &'static Shape<'static> = &const {
212
                Shape::builder_for_sized::<Self>()
213
                    .ty(Type::Sequence(SequenceType::Tuple(TupleType {
214
                        fields: &const {[
215
                            $(field_in_type!(Self, $idx),)+
216
                        ]}
217
                    })))
218
                    .build()
219
            };
220
        }
221

222
        impl_facet_for_tuple! {
223
            continue from ($($elems.$idx,)+),
224
            remaining ($($remaining.$remainingidx,)*)
225
        }
226
    };
227
    // The entry point into this macro, all smaller tuple types get implemented as well.
228
    { ($first:ident.$firstidx:tt $(, $remaining:ident.$remainingidx:tt)* $(,)?) } => {
229
        impl_facet_for_tuple! {
230
            impl ($first.$firstidx,),
231
            remaining ($($remaining.$remainingidx,)*)
232
        }
233
    };
234
}
235

236
impl_facet_for_tuple! {
237
    (T0.0, T1.1, T2.2, T3.3, T4.4, T5.5, T6.6, T7.7, T8.8, T9.9, T10.10, T11.11)
238
}
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