• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

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

90.29
/facet-macros-impl/src/process_struct.rs
1
//! Struct processing and vtable generation for the Facet derive macro.
2
//!
3
//! # Vtable Trait Detection
4
//!
5
//! The vtable contains function pointers for various trait implementations (Debug, Clone,
6
//! PartialEq, etc.). There are three ways these can be populated:
7
//!
8
//! ## 1. Derive Detection (Fastest - No Specialization)
9
//!
10
//! When `#[derive(Debug, Clone, Facet)]` is used, the macro can see the other derives
11
//! and knows those traits are implemented. It generates direct function pointers without
12
//! any specialization overhead.
13
//!
14
//! ```ignore
15
//! #[derive(Debug, Clone, Facet)]  // Debug and Clone detected from derives
16
//! struct Foo { ... }
17
//! ```
18
//!
19
//! ## 2. Explicit Declaration (No Specialization)
20
//!
21
//! For traits that are implemented manually (not via derive), use `#[facet(traits(...))]`:
22
//!
23
//! ```ignore
24
//! #[derive(Facet)]
25
//! #[facet(traits(Debug, PartialEq))]  // Explicit declaration
26
//! struct Foo { ... }
27
//!
28
//! impl Debug for Foo { ... }  // Manual implementation
29
//! impl PartialEq for Foo { ... }
30
//! ```
31
//!
32
//! This generates compile-time assertions to verify the traits are actually implemented.
33
//!
34
//! ## 3. Auto-Detection (Uses Specialization)
35
//!
36
//! For backward compatibility or when you don't want to list traits manually, use
37
//! `#[facet(auto_traits)]`. This uses the `impls!` macro to detect traits at compile
38
//! time via specialization tricks:
39
//!
40
//! ```ignore
41
//! #[derive(Debug, Facet)]
42
//! #[facet(auto_traits)]  // Auto-detect all other traits
43
//! struct Foo { ... }
44
//! ```
45
//!
46
//! **Note:** Auto-detection is slower to compile because it generates specialization
47
//! code for each trait. Use derive detection or explicit declaration when possible.
48
//!
49
//! ## Layered Resolution
50
//!
51
//! For each vtable entry, the macro checks sources in order:
52
//! 1. Is the trait in `#[derive(...)]`? → Use direct impl
53
//! 2. Is the trait in `#[facet(traits(...))]`? → Use direct impl
54
//! 3. Is `#[facet(auto_traits)]` present? → Use `impls!` detection
55
//! 4. Otherwise → Set to `None`
56
//!
57
//! Note: `#[facet(traits(...))]` and `#[facet(auto_traits)]` are mutually exclusive.
58
//! You can combine derives with either one:
59
//! ```ignore
60
//! #[derive(Debug, Clone, Facet)]  // Debug, Clone detected from derives
61
//! #[facet(traits(Display))]       // Display declared explicitly (manual impl)
62
//! struct Foo { ... }
63
//! ```
64

65
use quote::{format_ident, quote, quote_spanned};
66

67
use super::*;
68
use crate::parsed::{DeclaredTraits, KnownDerives, PAttrs};
69

70
/// Sources of trait information for vtable generation.
71
///
72
/// The vtable generation uses a layered approach:
73
/// 1. **Derives** - traits detected from `#[derive(...)]` next to `#[derive(Facet)]`
74
/// 2. **Declared** - traits explicitly listed in `#[facet(traits(...))]`
75
/// 3. **Implied** - traits implied by other attributes (e.g., `#[facet(default)]` implies Default)
76
/// 4. **Auto** - if `#[facet(auto_traits)]` is present, use `impls!` for remaining traits
77
/// 5. **None** - if none of the above apply, emit `None` for that trait
78
pub(crate) struct TraitSources<'a> {
79
    /// Traits detected from #[derive(...)] attributes
80
    pub known_derives: &'a KnownDerives,
81
    /// Traits explicitly declared via #[facet(traits(...))]
82
    pub declared_traits: Option<&'a DeclaredTraits>,
83
    /// Whether to auto-detect remaining traits via specialization
84
    pub auto_traits: bool,
85
    /// Whether `#[facet(default)]` is present (implies Default trait)
86
    pub facet_default: bool,
87
}
88

89
impl<'a> TraitSources<'a> {
90
    /// Create trait sources from parsed attributes
91
    pub fn from_attrs(attrs: &'a PAttrs) -> Self {
1,970✔
92
        Self {
1,970✔
93
            known_derives: &attrs.known_derives,
1,970✔
94
            declared_traits: attrs.declared_traits.as_ref(),
1,970✔
95
            auto_traits: attrs.auto_traits,
1,970✔
96
            facet_default: attrs.has_builtin("default"),
1,970✔
97
        }
1,970✔
98
    }
1,970✔
99

100
    /// Check if a trait is known from derives
101
    fn has_derive(&self, check: impl FnOnce(&KnownDerives) -> bool) -> bool {
17,788✔
102
        check(self.known_derives)
17,788✔
103
    }
17,788✔
104

105
    /// Check if a trait is explicitly declared
106
    fn has_declared(&self, check: impl FnOnce(&DeclaredTraits) -> bool) -> bool {
25,755✔
107
        self.declared_traits.is_some_and(check)
25,755✔
108
    }
25,755✔
109

110
    /// Check if we should use auto-detection for this trait
111
    fn should_auto(&self) -> bool {
17,725✔
112
        self.auto_traits
17,725✔
113
    }
17,725✔
114
}
115

116
/// Generates the vtable for a type based on trait sources.
117
///
118
/// Uses a layered approach for each trait:
119
/// 1. If known from derives → direct impl (no specialization)
120
/// 2. If explicitly declared → direct impl (no specialization)
121
/// 3. If auto_traits enabled → use `impls!` macro for detection
122
/// 4. Otherwise → None
123
pub(crate) fn gen_vtable(
1,970✔
124
    facet_crate: &TokenStream,
1,970✔
125
    type_name_fn: &TokenStream,
1,970✔
126
    sources: &TraitSources<'_>,
1,970✔
127
) -> TokenStream {
1,970✔
128
    // Helper to generate a direct implementation (no specialization)
129
    let direct_display = quote! {
1,970✔
130
        Some(|data, f| {
131
            let data = unsafe { data.get::<Self>() };
132
            core::fmt::Display::fmt(data, f)
133
        })
134
    };
135
    let direct_debug = quote! {
1,970✔
136
        Some(|data, f| {
137
            let data = unsafe { data.get::<Self>() };
138
            core::fmt::Debug::fmt(data, f)
139
        })
140
    };
141
    let direct_default = quote! {
1,970✔
142
        Some(|target| unsafe {
143
            target.put(<Self as core::default::Default>::default())
144
        })
145
    };
146
    let direct_clone = quote! {
1,970✔
147
        Some(|src, dst| unsafe {
148
            let src = src.get::<Self>();
149
            dst.put(<Self as core::clone::Clone>::clone(src))
150
        })
151
    };
152
    let direct_partial_eq = quote! {
1,970✔
153
        Some(|left, right| {
154
            let left = unsafe { left.get::<Self>() };
155
            let right = unsafe { right.get::<Self>() };
156
            <Self as core::cmp::PartialEq>::eq(left, right)
157
        })
158
    };
159
    let direct_partial_ord = quote! {
1,970✔
160
        Some(|left, right| {
161
            let left = unsafe { left.get::<Self>() };
162
            let right = unsafe { right.get::<Self>() };
163
            <Self as core::cmp::PartialOrd>::partial_cmp(left, right)
164
        })
165
    };
166
    let direct_ord = quote! {
1,970✔
167
        Some(|left, right| {
168
            let left = unsafe { left.get::<Self>() };
169
            let right = unsafe { right.get::<Self>() };
170
            <Self as core::cmp::Ord>::cmp(left, right)
171
        })
172
    };
173
    let direct_hash = quote! {
1,970✔
174
        Some(|value, hasher| {
175
            let value = unsafe { value.get::<Self>() };
176
            <Self as core::hash::Hash>::hash(value, hasher)
177
        })
178
    };
179

180
    // Auto-detection versions using spez
181
    let auto_display = quote! {
1,970✔
182
        if #facet_crate::spez::impls!(Self: core::fmt::Display) {
183
            Some(|data, f| {
184
                let data = unsafe { data.get::<Self>() };
185
                use #facet_crate::spez::*;
186
                (&&Spez(data)).spez_display(f)
187
            })
188
        } else {
189
            None
190
        }
191
    };
192
    let auto_debug = quote! {
1,970✔
193
        if #facet_crate::spez::impls!(Self: core::fmt::Debug) {
194
            Some(|data, f| {
195
                let data = unsafe { data.get::<Self>() };
196
                use #facet_crate::spez::*;
197
                (&&Spez(data)).spez_debug(f)
198
            })
199
        } else {
200
            None
201
        }
202
    };
203
    let auto_default = quote! {
1,970✔
204
        if #facet_crate::spez::impls!(Self: core::default::Default) {
205
            Some(|target| unsafe {
206
                use #facet_crate::spez::*;
207
                (&&SpezEmpty::<Self>::SPEZ).spez_default_in_place(target)
208
            })
209
        } else {
210
            None
211
        }
212
    };
213
    let auto_clone = quote! {
1,970✔
214
        if #facet_crate::spez::impls!(Self: core::clone::Clone) {
215
            Some(|src, dst| unsafe {
216
                use #facet_crate::spez::*;
217
                let src = src.get::<Self>();
218
                (&&Spez(src)).spez_clone_into(dst)
219
            })
220
        } else {
221
            None
222
        }
223
    };
224
    let auto_partial_eq = quote! {
1,970✔
225
        if #facet_crate::spez::impls!(Self: core::cmp::PartialEq) {
226
            Some(|left, right| {
227
                let left = unsafe { left.get::<Self>() };
228
                let right = unsafe { right.get::<Self>() };
229
                use #facet_crate::spez::*;
230
                (&&Spez(left)).spez_partial_eq(&&Spez(right))
231
            })
232
        } else {
233
            None
234
        }
235
    };
236
    let auto_partial_ord = quote! {
1,970✔
237
        if #facet_crate::spez::impls!(Self: core::cmp::PartialOrd) {
238
            Some(|left, right| {
239
                let left = unsafe { left.get::<Self>() };
240
                let right = unsafe { right.get::<Self>() };
241
                use #facet_crate::spez::*;
242
                (&&Spez(left)).spez_partial_cmp(&&Spez(right))
243
            })
244
        } else {
245
            None
246
        }
247
    };
248
    let auto_ord = quote! {
1,970✔
249
        if #facet_crate::spez::impls!(Self: core::cmp::Ord) {
250
            Some(|left, right| {
251
                let left = unsafe { left.get::<Self>() };
252
                let right = unsafe { right.get::<Self>() };
253
                use #facet_crate::spez::*;
254
                (&&Spez(left)).spez_cmp(&&Spez(right))
255
            })
256
        } else {
257
            None
258
        }
259
    };
260
    let auto_hash = quote! {
1,970✔
261
        if #facet_crate::spez::impls!(Self: core::hash::Hash) {
262
            Some(|value, hasher| {
263
                let value = unsafe { value.get::<Self>() };
264
                use #facet_crate::spez::*;
265
                (&&Spez(value)).spez_hash(&mut { hasher })
266
            })
267
        } else {
268
            None
269
        }
270
    };
271
    let auto_parse = quote! {
1,970✔
272
        if #facet_crate::spez::impls!(Self: core::str::FromStr) {
273
            Some(|s, target| {
274
                use #facet_crate::spez::*;
275
                unsafe { (&&SpezEmpty::<Self>::SPEZ).spez_parse(s, target) }
276
            })
277
        } else {
278
            None
279
        }
280
    };
281

282
    let none = quote! { None };
1,970✔
283

284
    // For each trait: derive > declared > auto > none
285
    // Display: no derive exists, so check declared then auto
286
    let display_entry = if sources.has_declared(|d| d.display) {
1,970✔
NEW
287
        direct_display
×
288
    } else if sources.should_auto() {
1,970✔
289
        auto_display
29✔
290
    } else {
291
        none.clone()
1,941✔
292
    };
293

294
    // Debug: check derive, then declared, then auto
295
    let debug_entry = if sources.has_derive(|d| d.debug) || sources.has_declared(|d| d.debug) {
1,970✔
296
        direct_debug
2✔
297
    } else if sources.should_auto() {
1,968✔
298
        auto_debug
29✔
299
    } else {
300
        none.clone()
1,939✔
301
    };
302

303
    // Default: check derive, then declared, then facet(default), then auto
304
    // Note: #[facet(default)] implies the type implements Default
305
    let default_entry = if sources.has_derive(|d| d.default)
1,970✔
306
        || sources.has_declared(|d| d.default)
1,970✔
307
        || sources.facet_default
1,970✔
308
    {
309
        direct_default
3✔
310
    } else if sources.should_auto() {
1,967✔
311
        auto_default
29✔
312
    } else {
313
        none.clone()
1,938✔
314
    };
315

316
    // Clone: check derive (including Copy which implies Clone), then declared, then auto
317
    let clone_entry = if sources.has_derive(|d| d.clone || d.copy)
1,970✔
318
        || sources.has_declared(|d| d.clone || d.copy)
1,970✔
319
    {
NEW
320
        direct_clone
×
321
    } else if sources.should_auto() {
1,970✔
322
        auto_clone
29✔
323
    } else {
324
        none.clone()
1,941✔
325
    };
326

327
    // PartialEq: check derive, then declared, then auto
328
    let partial_eq_entry =
1,970✔
329
        if sources.has_derive(|d| d.partial_eq) || sources.has_declared(|d| d.partial_eq) {
1,970✔
NEW
330
            direct_partial_eq
×
331
        } else if sources.should_auto() {
1,970✔
332
            auto_partial_eq
29✔
333
        } else {
334
            none.clone()
1,941✔
335
        };
336

337
    // PartialOrd: check derive, then declared, then auto
338
    let partial_ord_entry =
1,970✔
339
        if sources.has_derive(|d| d.partial_ord) || sources.has_declared(|d| d.partial_ord) {
1,970✔
NEW
340
            direct_partial_ord
×
341
        } else if sources.should_auto() {
1,970✔
342
            auto_partial_ord
29✔
343
        } else {
344
            none.clone()
1,941✔
345
        };
346

347
    // Ord: check derive, then declared, then auto
348
    let ord_entry = if sources.has_derive(|d| d.ord) || sources.has_declared(|d| d.ord) {
1,970✔
NEW
349
        direct_ord
×
350
    } else if sources.should_auto() {
1,970✔
351
        auto_ord
29✔
352
    } else {
353
        none.clone()
1,941✔
354
    };
355

356
    // Hash: check derive, then declared, then auto
357
    let hash_entry = if sources.has_derive(|d| d.hash) || sources.has_declared(|d| d.hash) {
1,970✔
NEW
358
        direct_hash
×
359
    } else if sources.should_auto() {
1,970✔
360
        auto_hash
29✔
361
    } else {
362
        none.clone()
1,941✔
363
    };
364

365
    // Parse (FromStr): no derive exists, only auto-detect if enabled
366
    let parse_entry = if sources.should_auto() {
1,970✔
367
        auto_parse
29✔
368
    } else {
369
        none.clone()
1,941✔
370
    };
371

372
    // Marker traits - these set bitflags in MarkerTraits
373
    // Copy: derive (Copy implies Clone), declared, or auto
374
    let has_copy =
1,970✔
375
        sources.has_derive(|d| d.copy) || sources.has_declared(|d| d.copy) || sources.auto_traits;
1,970✔
376
    // Send: declared or auto (no standard derive for Send)
377
    let has_send = sources.has_declared(|d| d.send) || sources.auto_traits;
1,970✔
378
    // Sync: declared or auto (no standard derive for Sync)
379
    let has_sync = sources.has_declared(|d| d.sync) || sources.auto_traits;
1,970✔
380
    // Eq: derive (PartialEq + Eq), declared, or auto
381
    let has_eq =
1,970✔
382
        sources.has_derive(|d| d.eq) || sources.has_declared(|d| d.eq) || sources.auto_traits;
1,970✔
383
    // Unpin: declared or auto (no standard derive for Unpin)
384
    let has_unpin = sources.has_declared(|d| d.unpin) || sources.auto_traits;
1,970✔
385

386
    // Build markers expression
387
    let markers_entry = if has_copy || has_send || has_sync || has_eq || has_unpin {
1,970✔
388
        // At least one marker trait might be set
389
        let copy_check = if has_copy
29✔
390
            && sources.auto_traits
29✔
391
            && !sources.has_derive(|d| d.copy)
29✔
392
            && !sources.has_declared(|d| d.copy)
29✔
393
        {
394
            // Auto-detect Copy
395
            quote! {
29✔
396
                if #facet_crate::spez::impls!(Self: core::marker::Copy) {
397
                    markers = markers.with_copy();
398
                }
399
            }
NEW
400
        } else if sources.has_derive(|d| d.copy) || sources.has_declared(|d| d.copy) {
×
401
            // Directly known to be Copy
NEW
402
            quote! { markers = markers.with_copy(); }
×
403
        } else {
NEW
404
            quote! {}
×
405
        };
406

407
        let send_check = if has_send && sources.auto_traits && !sources.has_declared(|d| d.send) {
29✔
408
            quote! {
29✔
409
                if #facet_crate::spez::impls!(Self: core::marker::Send) {
410
                    markers = markers.with_send();
411
                }
412
            }
NEW
413
        } else if sources.has_declared(|d| d.send) {
×
NEW
414
            quote! { markers = markers.with_send(); }
×
415
        } else {
NEW
416
            quote! {}
×
417
        };
418

419
        let sync_check = if has_sync && sources.auto_traits && !sources.has_declared(|d| d.sync) {
29✔
420
            quote! {
29✔
421
                if #facet_crate::spez::impls!(Self: core::marker::Sync) {
422
                    markers = markers.with_sync();
423
                }
424
            }
NEW
425
        } else if sources.has_declared(|d| d.sync) {
×
NEW
426
            quote! { markers = markers.with_sync(); }
×
427
        } else {
NEW
428
            quote! {}
×
429
        };
430

431
        let eq_check = if has_eq
29✔
432
            && sources.auto_traits
29✔
433
            && !sources.has_derive(|d| d.eq)
29✔
434
            && !sources.has_declared(|d| d.eq)
29✔
435
        {
436
            quote! {
29✔
437
                if #facet_crate::spez::impls!(Self: core::cmp::Eq) {
438
                    markers = markers.with_eq();
439
                }
440
            }
NEW
441
        } else if sources.has_derive(|d| d.eq) || sources.has_declared(|d| d.eq) {
×
NEW
442
            quote! { markers = markers.with_eq(); }
×
443
        } else {
NEW
444
            quote! {}
×
445
        };
446

447
        let unpin_check = if has_unpin && sources.auto_traits && !sources.has_declared(|d| d.unpin)
29✔
448
        {
449
            quote! {
29✔
450
                if #facet_crate::spez::impls!(Self: core::marker::Unpin) {
451
                    markers = markers.with_unpin();
452
                }
453
            }
NEW
454
        } else if sources.has_declared(|d| d.unpin) {
×
NEW
455
            quote! { markers = markers.with_unpin(); }
×
456
        } else {
NEW
457
            quote! {}
×
458
        };
459

460
        quote! {{
29✔
461
            let mut markers = #facet_crate::MarkerTraits::EMPTY;
462
            #copy_check
463
            #send_check
464
            #sync_check
465
            #eq_check
466
            #unpin_check
467
            markers
468
        }}
469
    } else {
470
        quote! { #facet_crate::MarkerTraits::EMPTY }
1,941✔
471
    };
472

473
    quote! {
1,970✔
474
        #facet_crate::ValueVTable::builder(#type_name_fn)
475
            .drop_in_place(#facet_crate::ValueVTable::drop_in_place_for::<Self>())
476
            .display_opt({ #display_entry })
477
            .debug_opt({ #debug_entry })
478
            .default_in_place_opt({ #default_entry })
479
            .clone_into_opt({ #clone_entry })
480
            .partial_eq_opt({ #partial_eq_entry })
481
            .partial_ord_opt({ #partial_ord_entry })
482
            .ord_opt({ #ord_entry })
483
            .hash_opt({ #hash_entry })
484
            .parse_opt({ #parse_entry })
485
            .markers({ #markers_entry })
486
            .build()
487
    }
488
}
1,970✔
489

490
/// Generate trait bounds for static assertions.
491
/// Returns a TokenStream of bounds like `core::fmt::Debug + core::clone::Clone`
492
/// that can be used in a where clause.
493
///
494
/// `facet_default` is true when `#[facet(default)]` is present, which implies Default.
495
pub(crate) fn gen_trait_bounds(
1,970✔
496
    declared: Option<&DeclaredTraits>,
1,970✔
497
    facet_default: bool,
1,970✔
498
) -> Option<TokenStream> {
1,970✔
499
    let mut bounds = Vec::new();
1,970✔
500

501
    if let Some(declared) = declared {
1,970✔
502
        if declared.display {
2✔
NEW
503
            bounds.push(quote! { core::fmt::Display });
×
504
        }
2✔
505
        if declared.debug {
2✔
506
            bounds.push(quote! { core::fmt::Debug });
2✔
507
        }
2✔
508
        if declared.clone {
2✔
NEW
509
            bounds.push(quote! { core::clone::Clone });
×
510
        }
2✔
511
        if declared.copy {
2✔
NEW
512
            bounds.push(quote! { core::marker::Copy });
×
513
        }
2✔
514
        if declared.partial_eq {
2✔
NEW
515
            bounds.push(quote! { core::cmp::PartialEq });
×
516
        }
2✔
517
        if declared.eq {
2✔
NEW
518
            bounds.push(quote! { core::cmp::Eq });
×
519
        }
2✔
520
        if declared.partial_ord {
2✔
NEW
521
            bounds.push(quote! { core::cmp::PartialOrd });
×
522
        }
2✔
523
        if declared.ord {
2✔
NEW
524
            bounds.push(quote! { core::cmp::Ord });
×
525
        }
2✔
526
        if declared.hash {
2✔
NEW
527
            bounds.push(quote! { core::hash::Hash });
×
528
        }
2✔
529
        if declared.default {
2✔
NEW
530
            bounds.push(quote! { core::default::Default });
×
531
        }
2✔
532
        if declared.send {
2✔
NEW
533
            bounds.push(quote! { core::marker::Send });
×
534
        }
2✔
535
        if declared.sync {
2✔
NEW
536
            bounds.push(quote! { core::marker::Sync });
×
537
        }
2✔
538
        if declared.unpin {
2✔
NEW
539
            bounds.push(quote! { core::marker::Unpin });
×
540
        }
2✔
541
    }
1,968✔
542

543
    // #[facet(default)] implies Default trait
544
    if facet_default && !declared.is_some_and(|d| d.default) {
1,970✔
545
        bounds.push(quote! { core::default::Default });
3✔
546
    }
1,967✔
547

548
    if bounds.is_empty() {
1,970✔
549
        None
1,965✔
550
    } else {
551
        Some(quote! { #(#bounds)+* })
5✔
552
    }
553
}
1,970✔
554

555
/// Generates the `::facet::Field` definition `TokenStream` from a `PStructField`.
556
pub(crate) fn gen_field_from_pfield(
3,377✔
557
    field: &PStructField,
3,377✔
558
    struct_name: &Ident,
3,377✔
559
    bgp: &BoundedGenericParams,
3,377✔
560
    base_offset: Option<TokenStream>,
3,377✔
561
    facet_crate: &TokenStream,
3,377✔
562
) -> TokenStream {
3,377✔
563
    let field_name_effective = &field.name.effective;
3,377✔
564
    let field_name_raw = &field.name.raw;
3,377✔
565
    let field_type = &field.ty;
3,377✔
566

567
    let bgp_without_bounds = bgp.display_without_bounds();
3,377✔
568

569
    let doc_lines: Vec<String> = field
3,377✔
570
        .attrs
3,377✔
571
        .doc
3,377✔
572
        .iter()
3,377✔
573
        .map(|doc| doc.as_str().replace("\\\"", "\""))
3,377✔
574
        .collect();
3,377✔
575

576
    // Generate the shape expression directly using the field type
577
    // For opaque fields, wrap in Opaque<T>
578
    let shape_expr = if field.attrs.has_builtin("opaque") {
3,377✔
579
        quote! { <#facet_crate::Opaque<#field_type> as #facet_crate::Facet>::SHAPE }
33✔
580
    } else {
581
        quote! { <#field_type as #facet_crate::Facet>::SHAPE }
3,344✔
582
    };
583

584
    // All attributes go through grammar dispatch
585
    // Note: deserialize_with and serialize_with have been REMOVED from the grammar.
586
    // Use #[facet(proxy = Type)] for custom serialization instead.
587
    let mut attribute_list: Vec<TokenStream> = field
3,377✔
588
        .attrs
3,377✔
589
        .facet
3,377✔
590
        .iter()
3,377✔
591
        .map(|attr| {
3,377✔
592
            let ext_attr = emit_attr_for_field(attr, field_name_raw, field_type, facet_crate);
1,464✔
593
            quote! { #ext_attr }
1,464✔
594
        })
1,464✔
595
        .collect();
3,377✔
596

597
    // Generate proxy conversion function pointers when proxy attribute is present
598
    if let Some(attr) = field
3,377✔
599
        .attrs
3,377✔
600
        .facet
3,377✔
601
        .iter()
3,377✔
602
        .find(|a| a.is_builtin() && a.key_str() == "proxy")
3,377✔
603
    {
39✔
604
        let proxy_type = &attr.args;
39✔
605

39✔
606
        // Generate __proxy_in: converts proxy -> field type via TryFrom
39✔
607
        attribute_list.push(quote! {
39✔
608
            #facet_crate::ExtensionAttr {
39✔
609
                ns: ::core::option::Option::None,
39✔
610
                key: "__proxy_in",
39✔
611
                data: &const {
39✔
612
                    extern crate alloc as __alloc;
39✔
613
                    unsafe fn __proxy_convert_in<'mem>(
39✔
614
                        proxy_ptr: #facet_crate::PtrConst<'mem>,
39✔
615
                        field_ptr: #facet_crate::PtrUninit<'mem>,
39✔
616
                    ) -> ::core::result::Result<#facet_crate::PtrMut<'mem>, __alloc::string::String> {
39✔
617
                        let proxy: #proxy_type = proxy_ptr.read();
39✔
618
                        match <#field_type as ::core::convert::TryFrom<#proxy_type>>::try_from(proxy) {
39✔
619
                            ::core::result::Result::Ok(value) => ::core::result::Result::Ok(field_ptr.put(value)),
39✔
620
                            ::core::result::Result::Err(e) => ::core::result::Result::Err(__alloc::string::ToString::to_string(&e)),
39✔
621
                        }
39✔
622
                    }
39✔
623
                    __proxy_convert_in as #facet_crate::ProxyConvertInFn
39✔
624
                } as *const #facet_crate::ProxyConvertInFn as *const (),
39✔
625
                shape: <() as #facet_crate::Facet>::SHAPE,
39✔
626
            }
39✔
627
        });
39✔
628

39✔
629
        // Generate __proxy_out: converts &field type -> proxy via TryFrom
39✔
630
        attribute_list.push(quote! {
39✔
631
            #facet_crate::ExtensionAttr {
39✔
632
                ns: ::core::option::Option::None,
39✔
633
                key: "__proxy_out",
39✔
634
                data: &const {
39✔
635
                    extern crate alloc as __alloc;
39✔
636
                    unsafe fn __proxy_convert_out<'mem>(
39✔
637
                        field_ptr: #facet_crate::PtrConst<'mem>,
39✔
638
                        proxy_ptr: #facet_crate::PtrUninit<'mem>,
39✔
639
                    ) -> ::core::result::Result<#facet_crate::PtrMut<'mem>, __alloc::string::String> {
39✔
640
                        let field_ref: &#field_type = field_ptr.get();
39✔
641
                        match <#proxy_type as ::core::convert::TryFrom<&#field_type>>::try_from(field_ref) {
39✔
642
                            ::core::result::Result::Ok(proxy) => ::core::result::Result::Ok(proxy_ptr.put(proxy)),
39✔
643
                            ::core::result::Result::Err(e) => ::core::result::Result::Err(__alloc::string::ToString::to_string(&e)),
39✔
644
                        }
39✔
645
                    }
39✔
646
                    __proxy_convert_out as #facet_crate::ProxyConvertOutFn
39✔
647
                } as *const #facet_crate::ProxyConvertOutFn as *const (),
39✔
648
                shape: <() as #facet_crate::Facet>::SHAPE,
39✔
649
            }
39✔
650
        });
39✔
651
    }
3,338✔
652

653
    let maybe_attributes = if attribute_list.is_empty() {
3,377✔
654
        quote! { &[] }
2,241✔
655
    } else {
656
        quote! { &const {[#(#attribute_list),*]} }
1,136✔
657
    };
658

659
    let maybe_field_doc = if doc_lines.is_empty() {
3,377✔
660
        quote! { &[] }
3,313✔
661
    } else {
662
        quote! { &[#(#doc_lines),*] }
64✔
663
    };
664

665
    // Calculate the final offset, incorporating the base_offset if present
666
    let final_offset = match base_offset {
3,377✔
667
        Some(base) => {
127✔
668
            quote! { #base + ::core::mem::offset_of!(#struct_name #bgp_without_bounds, #field_name_raw) }
127✔
669
        }
670
        None => {
671
            quote! { ::core::mem::offset_of!(#struct_name #bgp_without_bounds, #field_name_raw) }
3,250✔
672
        }
673
    };
674

675
    // Use FieldBuilder for more compact generated code
676
    let builder = quote! {
3,377✔
677
        #facet_crate::FieldBuilder::new(
678
            #field_name_effective,
679
            || #shape_expr,
680
            #final_offset,
681
        )
682
    };
683

684
    // Only chain .attributes() and .doc() if they have values
685
    let has_attrs = !attribute_list.is_empty();
3,377✔
686
    let has_doc = !doc_lines.is_empty();
3,377✔
687

688
    if has_attrs && has_doc {
3,377✔
689
        quote! { #builder.attributes(#maybe_attributes).doc(#maybe_field_doc).build() }
49✔
690
    } else if has_attrs {
3,328✔
691
        quote! { #builder.attributes(#maybe_attributes).build() }
1,087✔
692
    } else if has_doc {
2,241✔
693
        quote! { #builder.doc(#maybe_field_doc).build() }
15✔
694
    } else {
695
        quote! { #builder.build() }
2,226✔
696
    }
697
}
3,377✔
698

699
/// Processes a regular struct to implement Facet
700
///
701
/// Example input:
702
/// ```rust
703
/// struct Blah {
704
///     foo: u32,
705
///     bar: String,
706
/// }
707
/// ```
708
pub(crate) fn process_struct(parsed: Struct) -> TokenStream {
1,694✔
709
    let ps = PStruct::parse(&parsed); // Use the parsed representation
1,694✔
710

711
    // Emit any collected errors as compile_error! with proper spans
712
    if !ps.container.attrs.errors.is_empty() {
1,694✔
UNCOV
713
        let errors = ps.container.attrs.errors.iter().map(|e| {
×
UNCOV
714
            let msg = &e.message;
×
715
            let span = e.span;
×
716
            quote_spanned! { span => compile_error!(#msg); }
×
717
        });
×
718
        return quote! { #(#errors)* };
×
719
    }
1,694✔
720

721
    let struct_name_ident = format_ident!("{}", ps.container.name);
1,694✔
722
    let struct_name = &ps.container.name;
1,694✔
723
    let struct_name_str = struct_name.to_string();
1,694✔
724

725
    let opaque = ps.container.attrs.has_builtin("opaque");
1,694✔
726

727
    // Get the facet crate path (custom or default ::facet)
728
    let facet_crate = ps.container.attrs.facet_crate();
1,694✔
729

730
    let type_name_fn =
1,694✔
731
        generate_type_name_fn(struct_name, parsed.generics.as_ref(), opaque, &facet_crate);
1,694✔
732

733
    // Determine trait sources and generate vtable accordingly
734
    let trait_sources = TraitSources::from_attrs(&ps.container.attrs);
1,694✔
735
    let vtable_code = gen_vtable(&facet_crate, &type_name_fn, &trait_sources);
1,694✔
736
    let vtable_init = quote! { const { #vtable_code } };
1,694✔
737

738
    // TODO: I assume the `PrimitiveRepr` is only relevant for enums, and does not need to be preserved?
739
    let repr = match &ps.container.attrs.repr {
1,694✔
740
        PRepr::Transparent => quote! { #facet_crate::Repr::transparent() },
4✔
741
        PRepr::Rust(_) => quote! { #facet_crate::Repr::default() },
1,689✔
742
        PRepr::C(_) => quote! { #facet_crate::Repr::c() },
1✔
743
        PRepr::RustcWillCatch => {
744
            // rustc will emit an error for the invalid repr.
745
            // Return empty TokenStream so we don't add misleading errors.
UNCOV
746
            return quote! {};
×
747
        }
748
    };
749

750
    // Use PStruct for kind and fields
751
    let (kind, fields_vec) = match &ps.kind {
1,694✔
752
        PStructKind::Struct { fields } => {
1,591✔
753
            let kind = quote!(ʬSk::Struct);
1,591✔
754
            let fields_vec = fields
1,591✔
755
                .iter()
1,591✔
756
                .map(|field| {
2,665✔
757
                    gen_field_from_pfield(field, struct_name, &ps.container.bgp, None, &facet_crate)
2,665✔
758
                })
2,665✔
759
                .collect::<Vec<_>>();
1,591✔
760
            (kind, fields_vec)
1,591✔
761
        }
762
        PStructKind::TupleStruct { fields } => {
95✔
763
            let kind = quote!(ʬSk::TupleStruct);
95✔
764
            let fields_vec = fields
95✔
765
                .iter()
95✔
766
                .map(|field| {
118✔
767
                    gen_field_from_pfield(field, struct_name, &ps.container.bgp, None, &facet_crate)
118✔
768
                })
118✔
769
                .collect::<Vec<_>>();
95✔
770
            (kind, fields_vec)
95✔
771
        }
772
        PStructKind::UnitStruct => {
773
            let kind = quote!(ʬSk::Unit);
8✔
774
            (kind, vec![])
8✔
775
        }
776
    };
777

778
    // Still need original AST for where clauses and type params for build_ helpers
779
    let where_clauses_ast = match &parsed.kind {
1,694✔
780
        StructKind::Struct { clauses, .. } => clauses.as_ref(),
1,591✔
781
        StructKind::TupleStruct { clauses, .. } => clauses.as_ref(),
95✔
782
        StructKind::UnitStruct { clauses, .. } => clauses.as_ref(),
8✔
783
    };
784
    let where_clauses = build_where_clauses(
1,694✔
785
        where_clauses_ast,
1,694✔
786
        parsed.generics.as_ref(),
1,694✔
787
        opaque,
1,694✔
788
        &facet_crate,
1,694✔
789
    );
790
    let type_params = build_type_params(parsed.generics.as_ref(), opaque, &facet_crate);
1,694✔
791

792
    // Static decl using PStruct BGP
793
    let static_decl = if ps.container.bgp.params.is_empty() {
1,694✔
794
        generate_static_decl(struct_name, &facet_crate)
1,628✔
795
    } else {
796
        TokenStream::new()
66✔
797
    };
798

799
    // Doc comments from PStruct - returns value for struct literal
800
    let doc_field = if ps.container.attrs.doc.is_empty() {
1,694✔
801
        quote! { &[] }
1,662✔
802
    } else {
803
        let doc_lines = ps.container.attrs.doc.iter().map(|s| quote!(#s));
118✔
804
        quote! { &[#(#doc_lines),*] }
32✔
805
    };
806

807
    // Container attributes - most go through grammar dispatch
808
    // Filter out `invariants` and `crate` since they're handled specially
809
    // Returns value for struct literal
810
    let attributes_field = {
1,694✔
811
        let items: Vec<TokenStream> = ps
1,694✔
812
            .container
1,694✔
813
            .attrs
1,694✔
814
            .facet
1,694✔
815
            .iter()
1,694✔
816
            .filter(|attr| {
1,694✔
817
                // These attributes are handled specially and not emitted to runtime:
818
                // - invariants: populates vtable.invariants
819
                // - crate: sets the facet crate path
820
                // - traits: compile-time directive for vtable generation
821
                // - auto_traits: compile-time directive for vtable generation
822
                if attr.is_builtin() {
163✔
823
                    let key = attr.key_str();
148✔
824
                    !matches!(
34✔
825
                        key.as_str(),
148✔
826
                        "invariants" | "crate" | "traits" | "auto_traits"
148✔
827
                    )
828
                } else {
829
                    true
15✔
830
                }
831
            })
163✔
832
            .map(|attr| {
1,694✔
833
                let ext_attr = emit_attr(attr, &facet_crate);
129✔
834
                quote! { #ext_attr }
129✔
835
            })
129✔
836
            .collect();
1,694✔
837

838
        if items.is_empty() {
1,694✔
839
            quote! { &[] }
1,585✔
840
        } else {
841
            quote! { &const {[#(#items),*]} }
109✔
842
        }
843
    };
844

845
    // Type tag from PStruct - returns value for struct literal
846
    let type_tag_field = {
1,694✔
847
        if let Some(type_tag) = ps.container.attrs.get_builtin_args("type_tag") {
1,694✔
848
            quote! { Some(#type_tag) }
8✔
849
        } else {
850
            quote! { None }
1,686✔
851
        }
852
    };
853

854
    // Invariants from PStruct - extract invariant function expressions
855
    let invariant_maybe = {
1,694✔
856
        let invariant_exprs: Vec<&TokenStream> = ps
1,694✔
857
            .container
1,694✔
858
            .attrs
1,694✔
859
            .facet
1,694✔
860
            .iter()
1,694✔
861
            .filter(|attr| attr.is_builtin() && attr.key_str() == "invariants")
1,694✔
862
            .map(|attr| &attr.args)
1,694✔
863
            .collect();
1,694✔
864

865
        if !invariant_exprs.is_empty() {
1,694✔
866
            let tests = invariant_exprs.iter().map(|expr| {
3✔
867
                quote! {
3✔
868
                    if !#expr(value) {
869
                        return false;
870
                    }
871
                }
872
            });
3✔
873

874
            let bgp_display = ps.container.bgp.display_without_bounds();
3✔
875
            quote! {
3✔
876
                unsafe fn invariants<'mem>(value: #facet_crate::PtrConst<'mem>) -> bool {
877
                    let value = value.get::<#struct_name_ident #bgp_display>();
878
                    #(#tests)*
879
                    true
880
                }
881

882
                {
883
                    vtable.invariants = Some(invariants);
884
                }
885
            }
886
        } else {
887
            quote! {}
1,691✔
888
        }
889
    };
890

891
    // Transparent logic using PStruct
892
    let inner_field = if ps.container.attrs.has_builtin("transparent") {
1,694✔
893
        match &ps.kind {
36✔
894
            PStructKind::TupleStruct { fields } => {
36✔
895
                if fields.len() > 1 {
36✔
UNCOV
896
                    return quote! {
×
897
                        compile_error!("Transparent structs must be tuple structs with zero or one field");
898
                    };
899
                }
36✔
900
                fields.first().cloned() // Use first field if it exists, None otherwise (ZST case)
36✔
901
            }
902
            _ => {
UNCOV
903
                return quote! {
×
904
                    compile_error!("Transparent structs must be tuple structs");
905
                };
906
            }
907
        }
908
    } else {
909
        None
1,658✔
910
    };
911

912
    // Add try_from_inner implementation for transparent types
913
    let try_from_inner_code = if ps.container.attrs.has_builtin("transparent") {
1,694✔
914
        if let Some(inner_field) = &inner_field {
36✔
915
            if !inner_field.attrs.has_builtin("opaque") {
36✔
916
                // Transparent struct with one field
917
                let inner_field_type = &inner_field.ty;
34✔
918
                let bgp_without_bounds = ps.container.bgp.display_without_bounds();
34✔
919

920
                quote! {
34✔
921
                    // Define the try_from function for the value vtable
922
                    unsafe fn try_from<'src, 'dst>(
923
                        src_ptr: #facet_crate::PtrConst<'src>,
924
                        src_shape: &'static #facet_crate::Shape,
925
                        dst: #facet_crate::PtrUninit<'dst>
926
                    ) -> Result<#facet_crate::PtrMut<'dst>, #facet_crate::TryFromError> {
927
                        // Try the inner type's try_from function if it exists
928
                        let inner_result = match <#inner_field_type as #facet_crate::Facet>::SHAPE.vtable.try_from {
929
                            Some(inner_try) => unsafe { (inner_try)(src_ptr, src_shape, dst) },
930
                            None => Err(#facet_crate::TryFromError::UnsupportedSourceShape {
931
                                src_shape,
932
                                expected: const { &[ &<#inner_field_type as #facet_crate::Facet>::SHAPE ] },
933
                            })
934
                        };
935

936
                        match inner_result {
937
                            Ok(result) => Ok(result),
938
                            Err(_) => {
939
                                // If inner_try failed, check if source shape is exactly the inner shape
940
                                if src_shape != <#inner_field_type as #facet_crate::Facet>::SHAPE {
941
                                    return Err(#facet_crate::TryFromError::UnsupportedSourceShape {
942
                                        src_shape,
943
                                        expected: const { &[ &<#inner_field_type as #facet_crate::Facet>::SHAPE ] },
944
                                    });
945
                                }
946
                                // Read the inner value and construct the wrapper.
947
                                let inner: #inner_field_type = unsafe { src_ptr.read() };
948
                                Ok(unsafe { dst.put(inner) }) // Construct wrapper
949
                            }
950
                        }
951
                    }
952

953
                    // Define the try_into_inner function for the value vtable
954
                    unsafe fn try_into_inner<'src, 'dst>(
955
                        src_ptr: #facet_crate::PtrMut<'src>,
956
                        dst: #facet_crate::PtrUninit<'dst>
957
                    ) -> Result<#facet_crate::PtrMut<'dst>, #facet_crate::TryIntoInnerError> {
958
                        let wrapper = unsafe { src_ptr.get::<#struct_name_ident #bgp_without_bounds>() };
959
                        Ok(unsafe { dst.put(wrapper.0.clone()) }) // Assume tuple struct field 0
960
                    }
961

962
                    // Define the try_borrow_inner function for the value vtable
963
                    unsafe fn try_borrow_inner<'src>(
964
                        src_ptr: #facet_crate::PtrConst<'src>
965
                    ) -> Result<#facet_crate::PtrConst<'src>, #facet_crate::TryBorrowInnerError> {
966
                        let wrapper = unsafe { src_ptr.get::<#struct_name_ident #bgp_without_bounds>() };
967
                        // Return a pointer to the inner field (field 0 for tuple struct)
968
                        Ok(#facet_crate::PtrConst::new(::core::ptr::NonNull::from(&wrapper.0)))
969
                    }
970

971
                    {
972
                        vtable.try_from = Some(try_from);
973
                        vtable.try_into_inner = Some(try_into_inner);
974
                        vtable.try_borrow_inner = Some(try_borrow_inner);
975
                    }
976
                }
977
            } else {
978
                quote! {} // No try_from can be done for opaque
2✔
979
            }
980
        } else {
981
            // Transparent ZST struct (like struct Unit;)
UNCOV
982
            quote! {
×
983
                // Define the try_from function for the value vtable (ZST case)
984
                unsafe fn try_from<'src, 'dst>(
985
                    src_ptr: #facet_crate::PtrConst<'src>,
986
                    src_shape: &'static #facet_crate::Shape,
987
                    dst: #facet_crate::PtrUninit<'dst>
988
                ) -> Result<#facet_crate::PtrMut<'dst>, #facet_crate::TryFromError> {
989
                    if src_shape.layout.size() == 0 {
990
                         Ok(unsafe { dst.put(#struct_name_ident) }) // Construct ZST
991
                    } else {
992
                        Err(#facet_crate::TryFromError::UnsupportedSourceShape {
993
                            src_shape,
994
                            expected: const { &[ <() as #facet_crate::Facet>::SHAPE ] }, // Expect unit-like shape
995
                        })
996
                    }
997
                }
998

999
                {
1000
                    vtable.try_from = Some(try_from);
1001
                }
1002

1003
                // ZSTs cannot be meaningfully borrowed or converted *into* an inner value
1004
                // try_into_inner and try_borrow_inner remain None
1005
            }
1006
        }
1007
    } else {
1008
        quote! {} // Not transparent
1,658✔
1009
    };
1010

1011
    // Generate the inner shape field value for transparent types
1012
    let inner_field_val = if ps.container.attrs.has_builtin("transparent") {
1,694✔
1013
        let inner_shape_val = if let Some(inner_field) = &inner_field {
36✔
1014
            let ty = &inner_field.ty;
36✔
1015
            if inner_field.attrs.has_builtin("opaque") {
36✔
1016
                quote! { <#facet_crate::Opaque<#ty> as #facet_crate::Facet>::SHAPE }
2✔
1017
            } else {
1018
                quote! { <#ty as #facet_crate::Facet>::SHAPE }
34✔
1019
            }
1020
        } else {
1021
            // Transparent ZST case
UNCOV
1022
            quote! { <() as #facet_crate::Facet>::SHAPE }
×
1023
        };
1024
        quote! { Some(#inner_shape_val) }
36✔
1025
    } else {
1026
        quote! { None }
1,658✔
1027
    };
1028

1029
    // Generics from PStruct
1030
    let facet_bgp = ps
1,694✔
1031
        .container
1,694✔
1032
        .bgp
1,694✔
1033
        .with_lifetime(LifetimeName(format_ident!("__facet")));
1,694✔
1034
    let bgp_def = facet_bgp.display_with_bounds();
1,694✔
1035
    let bgp_without_bounds = ps.container.bgp.display_without_bounds();
1,694✔
1036

1037
    let (ty_field, fields) = if opaque {
1,694✔
1038
        (
2✔
1039
            quote! {
2✔
1040
                #facet_crate::Type::User(#facet_crate::UserType::Opaque)
2✔
1041
            },
2✔
1042
            quote! {},
2✔
1043
        )
2✔
1044
    } else {
1045
        // Optimize: use &[] for empty fields to avoid const block overhead
1046
        if fields_vec.is_empty() {
1,692✔
1047
            (
19✔
1048
                quote! {
19✔
1049
                    ʬTy::User(ʬUTy::Struct(
19✔
1050
                        ʬSTyB::new(#kind, &[]).repr(#repr).build()
19✔
1051
                    ))
19✔
1052
                },
19✔
1053
                quote! {},
19✔
1054
            )
19✔
1055
        } else {
1056
            // Inline the const block directly into the builder call
1057
            (
1058
                quote! {
1,673✔
1059
                    ʬTy::User(ʬUTy::Struct(
1060
                        ʬSTyB::new(#kind, &const {[#(#fields_vec),*]}).repr(#repr).build()
1061
                    ))
1062
                },
1063
                quote! {},
1,673✔
1064
            )
1065
        }
1066
    };
1067

1068
    // Generate code to suppress dead_code warnings on structs constructed via reflection.
1069
    // When structs are constructed via reflection (e.g., facet_args::from_std_args()),
1070
    // the compiler doesn't see them being used and warns about dead code.
1071
    // This function ensures the struct type is "used" from the compiler's perspective.
1072
    // See: https://github.com/facet-rs/facet/issues/996
1073
    let dead_code_suppression = quote! {
1,694✔
1074
        const _: () = {
1075
            #[allow(dead_code, clippy::multiple_bound_locations)]
1076
            fn __facet_use_struct #bgp_def (__v: &#struct_name_ident #bgp_without_bounds) #where_clauses {
1077
                let _ = __v;
1078
            }
1079
        };
1080
    };
1081

1082
    // Generate static assertions for declared traits (catches lies at compile time)
1083
    // We put this in a generic function outside the const block so it can reference generic parameters
1084
    let facet_default = ps.container.attrs.has_builtin("default");
1,694✔
1085
    let trait_assertion_fn = if let Some(bounds) =
1,694✔
1086
        gen_trait_bounds(ps.container.attrs.declared_traits.as_ref(), facet_default)
1,694✔
1087
    {
1088
        // Note: where_clauses already includes "where" keyword if non-empty
1089
        // We need to add the trait bounds as an additional constraint
1090
        quote! {
5✔
1091
            const _: () = {
1092
                #[allow(dead_code, clippy::multiple_bound_locations)]
1093
                fn __facet_assert_traits #bgp_def (_: &#struct_name_ident #bgp_without_bounds)
1094
                where
1095
                    #struct_name_ident #bgp_without_bounds: #bounds
1096
                {}
1097
            };
1098
        }
1099
    } else {
1100
        quote! {}
1,689✔
1101
    };
1102

1103
    // Final quote block using refactored parts
1104
    let result = quote! {
1,694✔
1105
        #static_decl
1106

1107
        #dead_code_suppression
1108

1109
        #trait_assertion_fn
1110

1111
        #[automatically_derived]
1112
        unsafe impl #bgp_def #facet_crate::Facet<'__facet> for #struct_name_ident #bgp_without_bounds #where_clauses {
1113
            const SHAPE: &'static #facet_crate::Shape = &const {
1114
                use #facet_crate::ʬ::*;
1115
                #fields
1116

1117
                ʬShp {
1118
                    id: ʬShp::id_of::<Self>(),
1119
                    layout: ʬShp::layout_of::<Self>(),
1120
                    vtable: {
1121
                        let mut vtable = #vtable_init;
1122
                        #invariant_maybe
1123
                        #try_from_inner_code // Use the generated code for transparent types
1124
                        vtable
1125
                    },
1126
                    ty: #ty_field,
1127
                    def: ʬDef::Undefined,
1128
                    type_identifier: #struct_name_str,
1129
                    type_params: #type_params,
1130
                    doc: #doc_field,
1131
                    attributes: #attributes_field,
1132
                    type_tag: #type_tag_field,
1133
                    inner: #inner_field_val,
1134
                }
1135
            };
1136
        }
1137
    };
1138

1139
    result
1,694✔
1140
}
1,694✔
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