const_panic/macros/
impl_panicfmt.rs

1/// Implements the [`PanicFmt`](crate::fmt::PanicFmt)
2/// trait and the `to_panicvals` method it requires.
3///
4/// For a derive macro alternative, there's the [`PanicFmt`](derive@crate::PanicFmt) derive,
5/// which requires the `"derive"` feature(disabled by default).
6///
7/// # Syntax
8///
9/// This macro roughly takes a type definition and a (conditionally required) list of impls,
10/// [for an example demonstrating all the parts of the syntax look here](#all-the-syntax).
11///
12/// This macro has these optional attributes that go above the item definition
13/// (and must go in this order):
14///
15/// - `#[pfmt(display_fmt = $display_fmt:expr)]`[**(example below)**](#display-example):
16/// Tells the macro to use the `$display_fmt` function to Display-format the type.
17///
18///
19/// - `#[pfmt(panicvals_lower_bound = $panicvals_lower_bound:expr)]`:
20/// Tells the macro to use at least `$panicvals_lower_bound` [`PanicVal`]s for
21/// formatting the type, useful for Display formatting with the
22/// `#[pfmt(display_fmt = ...)]` attribute.
23///
24///
25/// # Limitations
26///
27/// ### Type parameters
28///
29/// Types with type parameters can't be generically formatted, which has two workarounds.
30///
31/// The first workaround is marking a type parameter as ignored with an `ignore` prefix,
32/// if the type parameter(s) are only used in marker types (eg: `PhantomData`).
33/// [example of this workaround](#phantom-type-parameter-example)
34///
35/// The second workaround is to implement panic formatting with concrete type arguments,
36/// using trailing `(impl Foo<Bar>)`s.
37/// [example of this workaround](#type-parameter-example)
38///
39/// This limitation is caused by:
40/// - the lack of trait bound support in stable const fns.
41/// - the need to [have a concrete type argument](#concrete-pv-count)
42///
43/// [example below](#type-parameter-example)
44///
45/// ### Const parameters
46///
47/// Const parameters must not affect the value of the `PanicFmt::PV_COUNT`  of this type,
48/// since the const parameter [must be replaceable with a concrete value](#concrete-pv-count).
49/// <br>Note that arrays have a `PV_COUNT` of `1` for all lengths.
50///
51/// <a id = "concrete-pv-count"></a>
52/// ### Concrete `Self` type for `PanicFmt::PV_COUNT`
53///
54/// The `to_panicvals` method that this macro generates roughly returns a
55/// ```text
56/// [PanicVal<'_>; <Self as PanicFmt>::PV_COUNT]
57/// ```
58///
59/// Because of limitations in stable const generics,
60/// the generic arguments of `Self` in the above code must be replaced with concrete arguments,
61/// requiring:
62/// - Lifetime arguments to be replaced with `'_`
63/// - Type arguments to be replaced with concrete types (usually `()`)
64/// - Const arguments to be replaced with concrete values (usually the default value for the type)
65///
66/// # Examples
67///
68/// ### Struct formatting
69///
70/// ```rust
71/// use const_panic::{ArrayString, FmtArg, impl_panicfmt};
72///
73/// fn main(){
74///     const FOO: Foo = Foo {
75///         x: &[3, 5, 8, 13],
76///         y: 21,
77///         z: Bar(false, true),
78///     };
79///     
80///     assert_eq!(
81///         const_panic::concat_!(FmtArg::DEBUG; FOO),
82///         "Foo { x: [3, 5, 8, 13], y: 21, z: Bar(false, true) }",
83///     );
84///     assert_eq!(
85///         const_panic::concat_!(FmtArg::ALT_DEBUG; FOO),
86///         concat!(
87///             "Foo {\n",
88///             "    x: [\n",
89///             "        3,\n",
90///             "        5,\n",
91///             "        8,\n",
92///             "        13,\n",
93///             "    ],\n",
94///             "    y: 21,\n",
95///             "    z: Bar(\n",
96///             "        false,\n",
97///             "        true,\n",
98///             "    ),\n",
99///             "}",
100///         ),
101///     );
102/// }
103///
104///
105/// struct Foo<'a> {
106///     x: &'a [u8],
107///     y: u8,
108///     z: Bar,
109/// }
110///
111/// // Implementing `PanicFmt` and the `to_panicvals` method for `Foo<'a>`
112/// impl_panicfmt!{
113///     struct Foo<'a> {
114///         x: &'a [u8],
115///         y: u8,
116///         z: Bar,
117///     }
118/// }
119///
120///
121/// struct Bar(bool, bool);
122///
123/// impl_panicfmt!{
124///     struct Bar(bool, bool);
125/// }
126///
127/// ```
128///
129/// ### Enum Formatting
130///
131/// ```rust
132/// use const_panic::{ArrayString, FmtArg, impl_panicfmt};
133///
134/// fn main() {
135///     const UP: Qux<u8> = Qux::Up;
136///     // Debug formatting the Up variant
137///     assert_eq!(
138///         const_panic::concat_!(FmtArg::DEBUG; UP),
139///         "Up",
140///     );
141///
142///
143///     const DOWN: Qux<u16> = Qux::Down { x: 21, y: 34, z: 55 };
144///     // Debug formatting the Down variant
145///     assert_eq!(
146///         const_panic::concat_!(FmtArg::DEBUG; DOWN),
147///         "Down { x: 21, y: 34, z: 55 }",
148///     );
149///     // Alternate-Debug formatting the Down variant
150///     assert_eq!(
151///         const_panic::concat_!(FmtArg::ALT_DEBUG; DOWN),
152///         concat!(
153///             "Down {\n",
154///             "    x: 21,\n",
155///             "    y: 34,\n",
156///             "    z: 55,\n",
157///             "}",
158///         )
159///     );
160///
161///
162///     const LEFT: Qux<u32> = Qux::Left(89);
163///     // Debug formatting the Left variant
164///     assert_eq!(
165///         const_panic::concat_!(FmtArg::DEBUG; LEFT),
166///         "Left(89)",
167///     );
168///     // Alternate-Debug formatting the Left variant
169///     assert_eq!(
170///         const_panic::concat_!(FmtArg::ALT_DEBUG; LEFT),
171///         concat!(
172///             "Left(\n",
173///             "    89,\n",
174///             ")",
175///         )
176///     );
177/// }
178///
179/// enum Qux<T> {
180///     Up,
181///     Down { x: T, y: T, z: T },
182///     Left(u64),
183/// }
184///
185///
186/// // Because of limitations of stable const evaluation,
187/// // `Qux` can't generically implement panic formatting,
188/// // so this macro invocation implements panic formatting for these specifically:
189/// // - `Qux<u8>`
190/// // - `Qux<u16>`
191/// // - `Qux<u32>`
192/// impl_panicfmt!{
193///     enum Qux<T> {
194///         Up,
195///         Down { x: T, y: T, z: T },
196///         Left(u64),
197///     }
198///
199///     (impl Qux<u8>)
200///     (impl Qux<u16>)
201///     (impl Qux<u32>)
202/// }
203/// ```
204///
205/// <a id = "type-parameter-example"></a>
206/// ### Type parameters
207///
208/// This example demonstrates support for types with type parameters.
209///
210/// ```rust
211/// use const_panic::{ArrayString, FmtArg, impl_panicfmt};
212///
213/// use std::marker::PhantomData;
214///
215/// {
216///     const WITH_INT: Foo<&str, u8> = Foo {
217///         value: 100u8,
218///         _marker: PhantomData,
219///     };
220///     assert_eq!(
221///         const_panic::concat_!(FmtArg::DEBUG; WITH_INT),
222///         "Foo { value: 100, _marker: PhantomData }",
223///     );
224/// }
225/// {
226///     const WITH_STR: Foo<bool, &str> = Foo {
227///         value: "hello",
228///         _marker: PhantomData,
229///     };
230///     assert_eq!(
231///         const_panic::concat_!(FmtArg::DEBUG; WITH_STR),
232///         r#"Foo { value: "hello", _marker: PhantomData }"#,
233///     );
234/// }
235///
236/// #[derive(Debug)]
237/// pub struct Foo<A, B> {
238///     value: B,
239///     _marker: PhantomData<A>,
240/// }
241///
242/// impl_panicfmt!{
243///     // `ignore` here tells the macro that this type parameter is not formatted.
244///     struct Foo<ignore A, B> {
245///         value: B,
246///         _marker: PhantomData<A>,
247///     }
248///     
249///     // Because type parameters can't be generically formatted,
250///     // you need to list impls with concrete `B` type arguments.
251///     //
252///     // the generic parameters to the impl block go inside `[]`
253///     (impl[A] Foo<A, u8>)
254///     // the bounds in where clauses also go inside `[]`
255///     (impl[A] Foo<A, &str> where[A: 'static])
256/// }
257///
258///
259///
260/// ```
261///
262///
263/// <a id = "phantom-type-parameter-example"></a>
264/// ### Phantom Type parameters
265///
266/// This example demonstrates how type parameters can be ignored.
267///
268/// ```rust
269/// use const_panic::{ArrayString, FmtArg, impl_panicfmt};
270///
271/// use std::marker::PhantomData;
272///
273/// {
274///     const WITH_INT: Foo<u8, bool, 100> = Foo{
275///         value: 5,
276///         _marker: PhantomData,
277///     };
278///     assert_eq!(
279///         const_panic::concat_!(FmtArg::DEBUG; WITH_INT),
280///         "Foo { value: 5, _marker: PhantomData }",
281///     );
282/// }
283/// {
284///     const WITH_STR: Foo<str, char, 200> = Foo {
285///         value: 8,
286///         _marker: PhantomData,
287///     };
288///     assert_eq!(
289///         const_panic::concat_!(FmtArg::DEBUG; WITH_STR),
290///         r#"Foo { value: 8, _marker: PhantomData }"#,
291///     );
292/// }
293///
294/// #[derive(Debug)]
295/// pub struct Foo<A: ?Sized, B, const X: u32> {
296///     value: u32,
297///     _marker: PhantomData<(PhantomData<A>, B)>,
298/// }
299///
300/// impl_panicfmt!{
301///     // `ignore` here tells the macro that this type parameter is not formatted.
302///     //
303///     // `ignore(u8)` tells the macro to use `u8` as the `B` type parameter for
304///     // `<Foo<....> as PanicFmt>::PV_COUNT` in the generated `to_panicvals` method.
305///     struct Foo<ignore A, ignore(u8) B, const X: u32>
306///     // bounds must be written in the where clause, like this:
307///     where[ A: ?Sized ]
308///     {
309///         value: u32,
310///         _marker: PhantomData<(PhantomData<A>, B)>,
311///     }
312/// }
313/// ```
314///
315/// <a id = "display-example"></a>
316/// ### Display formatting
317///
318/// ```rust
319/// use const_panic::{impl_panicfmt, FmtArg, PanicFmt, PanicVal};
320///
321/// assert_eq!(const_panic::concat_!(debug: Foo([3, 5, 8])), "Foo([3, 5, 8])");
322/// assert_eq!(const_panic::concat_!(display: Foo([3, 5, 8])), "3 5 8");
323///
324/// struct Foo([u8; 3]);
325///
326/// impl_panicfmt! {
327///     // these (optional) attributes are the only supported struct-level attributes and
328///     // can only go in this order
329///     #[pfmt(display_fmt = Self::display_fmt)]
330///     // need this attribute to output more PanicVals in Display formatting than
331///     // in Debug formatting.
332///     #[pfmt(panicvals_lower_bound = 10)]
333///     struct Foo([u8; 3]);
334/// }
335///
336/// impl Foo {
337///     const fn display_fmt(&self, fmtarg: FmtArg) -> [PanicVal<'_>; Foo::PV_COUNT] {
338///         let [a, b, c] = self.0;
339///
340///         const_panic::flatten_panicvals!{fmtarg, Foo::PV_COUNT;
341///             a, " ", b, " ", c
342///         }
343///     }
344/// }
345///
346/// ```
347///
348/// <a id = "all-the-syntax"></a>
349/// ### All the syntax
350///
351/// ```rust
352/// # use const_panic::{impl_panicfmt, PanicFmt, PanicVal};
353/// # use const_panic::fmt::FmtArg;
354/// #
355/// # use std::marker::PhantomData;
356/// #
357/// # #[derive(Debug)]
358/// # pub struct Foo<'a, 'b, C, D, E, const X: u32>
359/// # where
360/// #    C: ?Sized,
361/// #    D: ?Sized,
362/// #    E: ?Sized,
363/// # {
364/// #     _lifetimes: PhantomData<(&'a (), &'b ())>,
365/// #     _marker: PhantomData<(PhantomData<C>, PhantomData<D>, PhantomData<E>)>,
366/// # }
367/// impl_panicfmt!{
368///     // these are the only supported struct-level attributes and can only go in this order
369///     #[pfmt(display_fmt = Self::display_fmt)]
370///     #[pfmt(panicvals_lower_bound = 100)]
371///     struct Foo<
372///         'a,
373///         'b,
374///         // For type parameters that aren't formatted.
375///         // Removes the `PanicFmt` bound on this type parameter
376///         // and uses `()` as the type argument for this to get
377///         // `<Foo<....> as PanicFmt>::PV_COUNT` in the generated `to_panicvals` methods.
378///         ignore C,
379///         // same as `C`, using `u8` instead of `()`
380///         ignore(u8) D,
381///         // un-`ignore`d type parameters must be replaced with concrete types in the impls below
382///         E,
383///         const X: u32,
384///     >
385///     // bounds must be written in the where clause, like this:
386///     where[ C: ?Sized, D: ?Sized, E: ?Sized ]
387///     {
388///         _lifetimes: PhantomData<(&'a (), &'b ())>,
389///         _marker: PhantomData<(PhantomData<C>, PhantomData<D>, PhantomData<E>)>,
390///     }
391///
392///     // The impls for this type, this is required for types with un-`ignore`d type parameters.
393///     // Otherwise, a generic impl is automatically generated.
394///     (
395///         impl['a, 'b, D, E: ?Sized, const X: u32] Foo<'a, 'b, D, E, u32, X>
396///         where[D: ?Sized]
397///     )
398///     (
399///         impl['a, 'b, D, E: ?Sized, const X: u32] Foo<'a, 'b, D, E, &str, X>
400///         where[D: ?Sized]
401///     )
402/// }
403///
404/// impl<'a, 'b, C, D, E, const X: u32> Foo<'a, 'b, C, D, E, X>
405/// where
406///     C: ?Sized,
407///     D: ?Sized,
408///     E: ?Sized,
409/// {
410///     const fn display_fmt(
411///         &self,
412///         fmt: FmtArg,
413///     ) -> [PanicVal<'_>; <Foo<'_, '_, (), u8, u32, 0>>::PV_COUNT] {
414///         const_panic::flatten_panicvals!{fmt, <Foo<'_, '_, (), u8, u32, 0>>::PV_COUNT;
415///             "Foo: ", X
416///         }
417///     }
418/// }
419///
420/// ```
421///
422/// [`PanicVal`]: crate::PanicVal
423#[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
424#[macro_export]
425macro_rules! impl_panicfmt {
426    (
427        $(# $attrs:tt)*
428        $kind:ident $typename:ident < $($rem:tt)*
429    ) => (
430        const _: () = {
431            // for intra-doc links
432            use $crate::{self as __cp_bCj7dq3Pud};
433
434            $crate::__impl_panicfmt_step_aaa!{
435                ($(# $attrs)* $kind $typename)
436                ()
437                ($($rem)*)
438            }
439        };
440    );
441    (
442        $(# $attrs:tt)*
443        $kind:ident $typename:ident $($rem:tt)*
444    ) => (
445        const _: () = {
446            // for intra-doc links
447            use $crate::{self as __cp_bCj7dq3Pud};
448
449            $crate::__impl_panicfmt_step_aaa!{
450                ($(# $attrs)* $kind $typename)
451                ()
452                (> $($rem)*)
453            }
454        };
455    );
456}
457
458#[doc(hidden)]
459#[macro_export]
460macro_rules! __impl_panicfmt_step_aaa {
461    (
462        ($(# $attrs:tt)* struct $struct_name:ident)
463        $generic_params:tt
464        (
465            $(,)? >
466            $(( $($tupled:tt)* ))?
467            $(where[$($where_preds:tt)*])?;
468
469            $($rem:tt)*
470        )
471    ) => (
472        $crate::__impl_panicfmt_step_ccc!{
473            [
474                $(# $attrs)*
475                struct $struct_name
476                $generic_params
477                ($($($where_preds)*)?)
478                $($rem)*
479            ]
480            []
481            [
482                $struct_name
483
484                ( $($($tupled)*)? )
485            ]
486        }
487    );
488    (
489        ($(# $attrs:tt)* struct $struct_name:ident)
490        $generic_params:tt
491        (
492            $(,)? >
493            $(where[$($where_preds:tt)*])?
494            $(( $($tupled:tt)* ))?;
495
496            $($rem:tt)*
497        )
498    ) => (
499        compile_error!{"the where clause must come after the tuple struct fields"}
500    );
501    (
502        ($(# $attrs:tt)* struct $struct_name:ident)
503        $generic_params:tt
504        (
505            $(,)?>
506            $(where[$($where_preds:tt)*])?
507            { $($braced:tt)* }
508
509            $($rem:tt)*
510        )
511    ) => (
512        $crate::__impl_panicfmt_step_ccc!{
513            [
514                $(# $attrs)*
515                struct $struct_name
516                $generic_params
517                ($($($where_preds)*)?)
518                $($rem)*
519            ]
520            []
521            [
522                $struct_name
523
524                { $($braced)* }
525            ]
526        }
527    );
528    (
529        ($(# $attrs:tt)* enum $enum_name:ident)
530        $generic_params:tt
531        (
532            $(,)?>
533            $(where[$($where_preds:tt)*])?
534            {
535                $(
536                    $variant:ident $({ $($braced:tt)* })? $(( $($tupled:tt)* ))?
537                ),*
538                $(,)?
539            }
540
541            $($rem:tt)*
542        )
543    ) => (
544        $crate::__impl_panicfmt_step_ccc!{
545            [
546                $(# $attrs)*
547                enum $enum_name
548                $generic_params
549                ($($($where_preds)*)?)
550                $($rem)*
551            ]
552            []
553            [
554                $(
555                    $variant $({ $($braced)* })? $(( $($tupled)* ))?,
556                )*
557            ]
558        }
559    );
560
561
562    ////////////////////////////////////
563
564    (
565        $fixed:tt
566        ($($prev_params:tt)*)
567        ($(,)? $(ignore)? $lifetime:lifetime  $($rem:tt)*)
568    ) => (
569        $crate::__impl_panicfmt_step_aaa!{
570            $fixed
571            ($($prev_params)* ($lifetime ($lifetime) ignore ('_)) )
572            ($($rem)*)
573        }
574    );
575    (
576        $fixed:tt
577        $prev_params:tt
578        ($(,)? $(ignore $(($($const_def:tt)*))? )? const $const_param:ident: $const_ty:ty , $($rem:tt)*)
579    ) => (
580        $crate::__impl_panicfmt_step_aaa_const!{
581            $fixed
582            ($(ignore $(($($const_def)*))? )?)
583            $prev_params
584            ($const_param: $const_ty)
585            ($($rem)*)
586        }
587    );
588    (
589        $fixed:tt
590        $prev_params:tt
591        ($(,)? $(ignore $(($($const_def:tt)*))? )? const $const_param:ident: $const_ty:ty > $($rem:tt)*)
592    ) => (
593        $crate::__impl_panicfmt_step_aaa_const!{
594            $fixed
595            ($(ignore $(($($const_def)*))? )?)
596            $prev_params
597            ($const_param: $const_ty)
598            (> $($rem)*)
599        }
600    );
601    (
602        $fixed:tt
603        ($($prev_params:tt)*)
604        ($(,)? ignore $(($ignore_ty:ty))? $type_param:ident $($rem:tt)*)
605    ) => (
606        $crate::__impl_panicfmt_step_aaa!{
607            $fixed
608            ($($prev_params)* ($type_param ($type_param) ignore (($($ignore_ty)?)) ) )
609            ($($rem)*)
610        }
611    );
612    (
613        $fixed:tt
614        ($($prev_params:tt)*)
615        ($(,)? $type_param:ident $($rem:tt)*)
616    ) => (
617        $crate::__impl_panicfmt_step_aaa!{
618            $fixed
619            (kept_type[$type_param] $($prev_params)* ($type_param ($type_param) kept ()) )
620            ($($rem)*)
621        }
622    );
623    (
624        $fixed:tt
625        $prev_params:tt
626        ($($rem:tt)+)
627    ) => (
628        $crate::__::compile_error!{concat!(
629            "could not parse this in the generic parameter(s) of the type definition:",
630            stringify!($($rem:tt)+)
631        )}
632    );
633}
634
635#[doc(hidden)]
636#[macro_export]
637macro_rules!  __impl_panicfmt_step_aaa_const {
638    (
639        $fixed:tt
640        (ignore($const_def:expr))
641        ($($prev_params:tt)*)
642        ($const_param:ident: $const_ty:ty)
643        $rem:tt
644    ) => {
645        $crate::__impl_panicfmt_step_aaa!{
646            $fixed
647            (
648                $($prev_params)*
649                (
650                    $const_param
651                    (const $const_param: $const_ty)
652                    ignore ({$const_def})
653                )
654            )
655            $rem
656        }
657    };
658    (
659        $fixed:tt
660        ($(ignore)?)
661        ($($prev_params:tt)*)
662        ($const_param:ident: $const_ty:ty)
663        $rem:tt
664    ) => {
665        $crate::__impl_panicfmt_step_aaa!{
666            $fixed
667            (
668                $($prev_params)*
669                (
670                    $const_param
671                    (const $const_param: $const_ty)
672                    ignore ({$crate::__::ConstDefault::DEFAULT})
673                )
674            )
675            $rem
676        }
677    };
678}
679
680#[doc(hidden)]
681#[macro_export]
682macro_rules!  __impl_panicfmt_step_ccc {
683    (
684        $kept:tt
685        $prev_variants:tt
686        [
687            $variant:ident
688            $($(@$is_brace:tt@)? {$($br_field:ident: $br_ty:ty),* $(,)*})?
689            $($(@$is_tuple:tt@)? ( $($tup_ty:ty),* $(,)* ))?
690            $(,$($rem_variants:tt)*)?
691        ]
692    ) => {
693        $crate::zip_counter_and_last!{
694            $crate::__impl_panicfmt_step_ccc_inner!{
695                $kept
696                $prev_variants
697                $variant
698                (
699                    $($($is_brace)? Braced)?
700                    $($($is_tuple)? Tupled)?
701                    Braced
702                )
703                [$($($rem_variants)*)?]
704            }
705            ($($(($br_field, $br_ty))*)? $($((, $tup_ty))*)?)
706            (
707                (0 fi0) (1 fi1) (2 fi2) (3 fi3) (4 fi4) (5 fi5) (6 fi6) (7 fi7)
708                (8 fi8) (9 fi9) (10 fi10) (11 fi11) (12 fi12) (13 fi13) (14 fi14) (15 fi15)
709                (16 fi16) (17 fi17) (18 fi18) (19 fi19) (20 fi20) (21 fi21) (22 fi22) (23 fi23)
710                (24 fi24) (25 fi25) (26 fi26) (27 fi27) (28 fi28) (29 fi29) (30 fi30) (31 fi31)
711                (32 fi32) (33 fi33) (34 fi34) (35 fi35) (36 fi36) (37 fi37) (38 fi38) (39 fi39)
712                (40 fi40) (41 fi41) (42 fi42) (43 fi43) (44 fi44) (45 fi45) (46 fi46) (47 fi47)
713                (48 fi48) (49 fi49) (50 fi50) (51 fi51) (52 fi52) (53 fi53) (54 fi54) (55 fi55)
714                (56 fi56) (57 fi57) (58 fi58) (59 fi59) (60 fi60) (61 fi61) (62 fi62) (63 fi63)
715            )
716        }
717    };
718    // Parsing unit variants / structs
719    (
720        $kept:tt
721        [$($prev_variants:tt)*]
722        [
723            $variant:ident
724            $(, $($rem_variants:tt)*)?
725        ]
726    ) => {
727        $crate::__impl_panicfmt_step_ccc!{
728            $kept
729            [$($prev_variants)* ($variant Braced) ]
730            [$($($rem_variants)*)?]
731        }
732    };
733    // Finished parsing variants/structs,
734    //
735    (
736        $kept:tt
737        $variants:tt
738        []
739    ) => {
740        $crate::__impl_panicfmt_step__panicfmt_impl!{
741            $kept
742            variants $variants
743
744            $kept
745            $variants
746        }
747    };
748}
749
750#[doc(hidden)]
751#[macro_export]
752macro_rules!  __impl_panicfmt_step_ccc_inner {
753    (
754        $kept:tt
755        [$($prev_variants:tt)*]
756        $variant:ident
757        ($delim:ident $($ignore0:tt)*)
758        [$($rem_variants:tt)*]
759
760        $(prefix (($($p_fname:ident)?, $p_ty:ty) ($p_index:tt $p_fi_index:tt)))*
761        $(last (($($l_fname:ident)?, $l_ty:ty) ($l_index:tt $l_fi_index:tt)) )?
762    ) => {
763        $crate::__impl_panicfmt_step_ccc!{
764            $kept
765            [
766                $($prev_variants)*
767                (
768                    $variant
769                    $delim
770                    ($($l_index + 1,)? 0,)
771                    =>
772                    $(prefix (($($p_fname)? $p_index), ($($p_fname)? $p_fi_index), $p_ty))*
773                    $(last (($($l_fname)? $l_index), ($($l_fname)? $l_fi_index), $l_ty))?
774                )
775            ]
776            [$($rem_variants)*]
777        }
778    };
779}
780
781#[doc(hidden)]
782#[macro_export]
783macro_rules!  __impl_panicfmt_step__panicfmt_impl {
784    (
785
786        [
787            $(#[pfmt(display_fmt = $__display_fmt:expr)])?
788            $(#[pfmt(panicvals_lower_bound = $panicvals_lower_bound:expr)])?
789            $type_kind:ident $type_name:ident
790            (
791                $($kept_type:ident [$kept_type_:ident])*
792                $((
793                    $gp_arg:tt
794                    ($($gp_param:tt)*)
795                    $ignorance:tt
796                    ($($gp_arg_concrete:tt)*)
797                ))*
798            )
799            ($($where_preds:tt)*)
800
801            $($to_panicval_impls:tt)*
802        ]
803
804        variants[$(
805            (
806                $variant:ident
807                $delimiter:ident
808                ($field_amount:expr, $($ignore2:tt)*)
809                =>
810                $(
811                    $is_last_field:ident
812                    (
813                        ($fpati:tt $($ignore3:tt)?),
814                        ($fname:tt $($ignore4:tt)?),
815                        $ty:ty
816                    )
817                )*
818            )
819        )*]
820
821        $kept:tt
822        $variants:tt
823    ) => (
824        impl<$($($gp_param)*),*> $crate::PanicFmt for $type_name<$($gp_arg),*>
825        where
826            $($kept_type_: $crate::PanicFmt,)*
827            $($where_preds)*
828        {
829            type This = Self;
830            type Kind = $crate::fmt::IsCustomType;
831
832            const PV_COUNT: $crate::__::usize = $crate::utils::slice_max_usize(&[
833                $(
834                    $crate::fmt::ComputePvCount{
835                        field_amount: $field_amount,
836                        summed_pv_count: 0 $( + <$ty as $crate::PanicFmt>::PV_COUNT )*,
837                        delimiter: $crate::fmt::TypeDelim::$delimiter
838                    }.call(),
839                )*
840                $($panicvals_lower_bound)?
841            ]);
842        }
843
844        macro_rules! __assert_type_name__ {
845            ($type_name) => ()
846        }
847
848        $crate::__impl_to_panicvals!{
849            [$($kept_type)*]
850            [$($ignorance ($($gp_arg_concrete)*))*]
851            [
852                $type_name
853                [$($where_preds)*]
854                $((
855                    ($($gp_param)*)
856                    $gp_arg
857                ))*
858            ]
859            [$($to_panicval_impls)*]
860            $kept
861            $variants
862        }
863    );
864}
865
866#[doc(hidden)]
867#[macro_export]
868macro_rules! __impl_to_panicvals {
869    (
870        [$(kept_type)*]
871        $ignorances:tt
872        $gp_param:tt
873        [$($to_panicval_impls:tt)+]
874        $kept:tt
875        $variants:tt
876    ) => (
877        $(
878            $crate::__impl_to_panicvals_step_aaa!{
879                $ignorances
880                $to_panicval_impls
881                $to_panicval_impls
882                $kept
883                $variants
884            }
885        )*
886    );
887    (
888        []
889        $ignorances:tt
890        [$type_name:ident [$($where_preds:tt)*] $(( ($($gp_param:tt)*) $gp_arg:tt ))* ]
891        []
892        $kept:tt
893        $variants:tt
894    ) => (
895        $crate::__impl_to_panicvals_step_aaa!{
896            $ignorances
897            (
898                impl[$($($gp_param)*),*] $type_name<$($gp_arg),*>
899                where[$($where_preds)*]
900            )
901            (
902                impl[$($($gp_param)*),*] $type_name<$($gp_arg),*>
903                where[$($where_preds)*]
904            )
905            $kept
906            $variants
907        }
908    );
909    ([$(kept_type)+] $ignorances:tt $gp_param:tt [] $kept:tt $variants:tt) => (
910        $crate::__::compile_error!{"\
911            type parameters must either be:\n\
912            - all prefixed with ignore\n\
913            - be replaced with concrete type arguments in \
914            `(impl Foo<Bar>)`s after the type definition\n\
915        "}
916    );
917}
918
919#[doc(hidden)]
920#[macro_export]
921macro_rules! __impl_to_panicvals_step_aaa {
922    (
923        $ignorances:tt
924        (impl $([$($impl_param:tt)*])? $type_name:ident $(where $where_preds:tt)?)
925        $impl:tt
926        $kept:tt
927        $variants:tt
928    ) => {
929        __assert_type_name__!{$type_name}
930
931        $crate::__impl_to_panicvals_step_bbb!{
932            ([$($($impl_param)*)?] $type_name $kept $variants)
933            $ignorances
934            []
935            [> $(where $where_preds)?]
936        }
937    };
938    (
939        $ignorances:tt
940        (impl $([$($impl_param:tt)*])? $type_name:ident <$($args:tt)*)
941        (impl $([$($impl_paramb:tt)*])? $type:path $(where $where_preds:tt)? )
942        $kept:tt
943        $variants:tt
944    ) => {
945        __assert_type_name__!{$type_name}
946
947        $crate::__impl_to_panicvals_step_bbb!{
948            ([$($($impl_param)*)?] $type $kept $variants)
949            $ignorances
950            []
951            [$($args)*]
952        }
953    };
954}
955
956#[doc(hidden)]
957#[macro_export]
958macro_rules! __impl_to_panicvals_step_bbb {
959    // finished parsing
960    (
961        $kept:tt
962        []
963        $cself:tt
964        [> $(where[$($where_preds:tt)*])?]
965    ) => {
966        $crate::__impl_to_panicvals_finish!{
967            $kept
968            [$($($where_preds)*)?]
969            $cself
970        }
971    };
972
973
974
975    // const or lifetime argument
976    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $gen_arg:tt , $($rem:tt)*]) => {
977        $crate::__impl_to_panicvals_step_bbb_inner!{
978            $kept
979            $ignorance
980            [$gen_arg]
981            $prev_cself
982            [$($rem)*]
983        }
984    };
985    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $gen_arg:tt > $($rem:tt)*]) => {
986        $crate::__impl_to_panicvals_step_bbb_inner!{
987            $kept
988            $ignorance
989            [$gen_arg]
990            $prev_cself
991            [> $($rem)*]
992        }
993    };
994
995    // type argument
996    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $ty_arg:ty , $($rem:tt)* ]) => {
997        $crate::__impl_to_panicvals_step_bbb_inner!{
998            $kept
999            $ignorance
1000            [$ty_arg]
1001            $prev_cself
1002            [$($rem)*]
1003        }
1004    };
1005    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $ty_arg:ty > $($rem:tt)*]) => {
1006        $crate::__impl_to_panicvals_step_bbb_inner!{
1007            $kept
1008            $ignorance
1009            [$ty_arg]
1010            $prev_cself
1011            [> $($rem)*]
1012        }
1013    };
1014}
1015
1016#[doc(hidden)]
1017#[macro_export]
1018macro_rules! __impl_to_panicvals_step_bbb_inner {
1019    (
1020        $kept:tt
1021        [kept $gp_arg_concrete:tt $($rem_ignorance:tt)*]
1022        [$gen_arg:tt]
1023        [$($prev_cself:tt)*]
1024        $rem:tt
1025    ) => {
1026        $crate::__impl_to_panicvals_step_bbb!{
1027            $kept
1028            [$($rem_ignorance)*]
1029            [$($prev_cself)* $gen_arg,]
1030            $rem
1031        }
1032    };
1033    (
1034        $kept:tt
1035        [ignore ($($gp_arg_concrete:tt)*) $($rem_ignorance:tt)*]
1036        $gen_arg:tt
1037        [$($prev_cself:tt)*]
1038        $rem:tt
1039    ) => {
1040        $crate::__impl_to_panicvals_step_bbb!{
1041            $kept
1042            [$($rem_ignorance)*]
1043            [$($prev_cself)* $($gp_arg_concrete)*,]
1044            $rem
1045        }
1046    };
1047}
1048
1049#[doc(hidden)]
1050#[macro_export]
1051macro_rules! __impl_to_panicvals_finish {
1052    // finished parsing
1053    (
1054        (
1055            [$($impl_param:tt)*]
1056            $type:ty
1057
1058            [
1059                $(#[pfmt(display_fmt = $display_fmt:expr)])?
1060                $(#[pfmt(panicvals_lower_bound = $__panicvals_lower_bound:expr)])?
1061                $type_kind:ident $type_name:ident
1062                $generics:tt
1063                $type_where_preds:tt
1064
1065                $($to_panicval_impls:tt)*
1066            ]
1067
1068            [$(
1069                (
1070                    $variant:ident
1071                    $delimiter:ident
1072                    ($field_amount:expr, $($ignore2:tt)*)
1073                    =>
1074                    $(
1075                        $is_last_field:ident
1076                        (
1077                            ($fpati:tt $($ignore3:tt)?),
1078                            ($fname:tt $($ignore4:tt)?),
1079                            $ty:ty
1080                        )
1081                    )*
1082                )
1083            )*]
1084
1085        )
1086        [ $($where_preds:tt)* ]
1087        $cself:tt
1088    ) => {
1089        /// Provides the required `to_panicvals` method for
1090        /// [`const_panic::fmt::PanicFmt` trait](trait@__cp_bCj7dq3Pud::fmt::PanicFmt)
1091        #[automatically_derived]
1092        impl<$($impl_param)*> $type
1093        where
1094            $($where_preds)*
1095        {
1096            /// Gets the `PanicVal`s for
1097            /// [`const_panic`](__cp_bCj7dq3Pud)-based
1098            /// formatting of this value.
1099            pub const fn to_panicvals(
1100                &self,
1101                mut fmt: $crate::FmtArg,
1102            ) -> [$crate::PanicVal<'_>; $crate::__ipm_cself!($type_name $cself)] {
1103                $(
1104                    if let $crate::fmt::FmtKind::Display = fmt.fmt_kind {
1105                        $display_fmt(self, fmt)
1106                    } else
1107                )? {
1108                    match self {
1109                        $(
1110                            $crate::__ipm_pattern!($type_kind $variant{$($fpati: $fname,)* ..}) =>
1111                                $crate::__ipm_fmt!{
1112                                    ($crate::__ipm_cself!($type_name $cself))
1113                                    $delimiter
1114                                    $variant
1115                                    fmt
1116                                    ( $($is_last_field ($fname, $ty))* )
1117                                },
1118                        )*
1119                    }
1120                }
1121            }
1122        }
1123    };
1124}
1125
1126#[doc(hidden)]
1127#[macro_export]
1128macro_rules!  __ipm_pattern {
1129    (struct $name:ident {$($patterns:tt)*}) => {
1130        $name {$($patterns)*}
1131    };
1132    (enum $name:ident {$($patterns:tt)*}) => {
1133        Self::$name {$($patterns)*}
1134    };
1135}
1136
1137#[doc(hidden)]
1138#[macro_export]
1139macro_rules!  __ipm_fmt {
1140    (
1141        ($count:expr) $delimiter:ident $typename:ident $fmt:ident
1142        ( $($is_last_field:ident ($fname:ident, $ty:ty))+ )
1143    ) => ({
1144        let (open, close) = $crate::fmt::TypeDelim::$delimiter.get_open_and_close();
1145
1146        $crate::__::flatten_panicvals::<{$count}>(&[
1147            &[
1148                $crate::PanicVal::write_str($crate::__::stringify!($typename)),
1149                {
1150                    $fmt = $fmt.indent();
1151                    open.to_panicval($fmt)
1152                }
1153            ],
1154            $(
1155                $crate::__ipm_pv_fmt_field_name!($delimiter $fname),
1156                &$crate::PanicFmt::PROOF
1157                    .infer($fname)
1158                    .coerce($fname)
1159                    .to_panicvals($fmt),
1160                &$crate::__ipm_pv_comma!($is_last_field)
1161                    .to_panicvals($fmt),
1162            )*
1163            &[
1164                {
1165                    $fmt = $fmt.unindent();
1166                    close.to_panicval($fmt)
1167                }
1168            ],
1169        ])
1170    });
1171    (
1172        ($count:expr) $delimiter:ident $typename:ident $fmt:ident
1173        ()
1174    ) => {
1175        $crate::__::flatten_panicvals::<{$count}>(&[
1176            &[$crate::PanicVal::write_str($crate::__::stringify!($typename))]
1177        ])
1178    }
1179}
1180
1181#[doc(hidden)]
1182#[macro_export]
1183macro_rules! __ipm_pv_fmt_field_name {
1184    (Tupled $field_name:ident) => {
1185        &[]
1186    };
1187    (Braced $field_name:ident) => {
1188        &[$crate::PanicVal::write_str($crate::__::concat!(
1189            $crate::__::stringify!($field_name),
1190            ": "
1191        ))]
1192    };
1193}
1194
1195#[doc(hidden)]
1196#[macro_export]
1197macro_rules! __ipm_pv_comma {
1198    (prefix) => {
1199        $crate::fmt::COMMA_SEP
1200    };
1201    (last) => {
1202        $crate::fmt::COMMA_TERM
1203    };
1204}
1205
1206#[doc(hidden)]
1207#[macro_export]
1208macro_rules! __ipm_cself {
1209    ($type_name:ident [$($cself:tt)*]) => {
1210        <$type_name<$($cself)*> as $crate::PanicFmt>::PV_COUNT
1211    };
1212}