Skip to main content

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            #[allow(unused_imports)]
433            use $crate::{self as __cp_bCj7dq3Pud};
434
435            $crate::__impl_panicfmt_step_aaa!{
436                ($(# $attrs)* $kind $typename)
437                ()
438                ($($rem)*)
439            }
440        };
441    );
442    (
443        $(# $attrs:tt)*
444        $kind:ident $typename:ident $($rem:tt)*
445    ) => (
446        const _: () = {
447            // for intra-doc links
448            #[allow(unused_imports)]
449            use $crate::{self as __cp_bCj7dq3Pud};
450
451            $crate::__impl_panicfmt_step_aaa!{
452                ($(# $attrs)* $kind $typename)
453                ()
454                (> $($rem)*)
455            }
456        };
457    );
458}
459
460#[doc(hidden)]
461#[macro_export]
462macro_rules! __impl_panicfmt_step_aaa {
463    (
464        ($(# $attrs:tt)* struct $struct_name:ident)
465        $generic_params:tt
466        (
467            $(,)? >
468            $(( $($tupled:tt)* ))?
469            $(where[$($where_preds:tt)*])?;
470
471            $($rem:tt)*
472        )
473    ) => (
474        $crate::__impl_panicfmt_step_ccc!{
475            [
476                $(# $attrs)*
477                struct $struct_name
478                $generic_params
479                ($($($where_preds)*)?)
480                $($rem)*
481            ]
482            []
483            [
484                $struct_name
485
486                ( $($($tupled)*)? )
487            ]
488        }
489    );
490    (
491        ($(# $attrs:tt)* struct $struct_name:ident)
492        $generic_params:tt
493        (
494            $(,)? >
495            $(where[$($where_preds:tt)*])?
496            $(( $($tupled:tt)* ))?;
497
498            $($rem:tt)*
499        )
500    ) => (
501        compile_error!{"the where clause must come after the tuple struct fields"}
502    );
503    (
504        ($(# $attrs:tt)* struct $struct_name:ident)
505        $generic_params:tt
506        (
507            $(,)?>
508            $(where[$($where_preds:tt)*])?
509            { $($braced:tt)* }
510
511            $($rem:tt)*
512        )
513    ) => (
514        $crate::__impl_panicfmt_step_ccc!{
515            [
516                $(# $attrs)*
517                struct $struct_name
518                $generic_params
519                ($($($where_preds)*)?)
520                $($rem)*
521            ]
522            []
523            [
524                $struct_name
525
526                { $($braced)* }
527            ]
528        }
529    );
530    (
531        ($(# $attrs:tt)* enum $enum_name:ident)
532        $generic_params:tt
533        (
534            $(,)?>
535            $(where[$($where_preds:tt)*])?
536            {
537                $(
538                    $variant:ident $({ $($braced:tt)* })? $(( $($tupled:tt)* ))?
539                ),*
540                $(,)?
541            }
542
543            $($rem:tt)*
544        )
545    ) => (
546        $crate::__impl_panicfmt_step_ccc!{
547            [
548                $(# $attrs)*
549                enum $enum_name
550                $generic_params
551                ($($($where_preds)*)?)
552                $($rem)*
553            ]
554            []
555            [
556                $(
557                    $variant $({ $($braced)* })? $(( $($tupled)* ))?,
558                )*
559            ]
560        }
561    );
562
563
564    ////////////////////////////////////
565
566    (
567        $fixed:tt
568        ($($prev_params:tt)*)
569        ($(,)? $(ignore)? $lifetime:lifetime  $($rem:tt)*)
570    ) => (
571        $crate::__impl_panicfmt_step_aaa!{
572            $fixed
573            ($($prev_params)* ($lifetime ($lifetime) ignore ('_)) )
574            ($($rem)*)
575        }
576    );
577    (
578        $fixed:tt
579        $prev_params:tt
580        ($(,)? $(ignore $(($($const_def:tt)*))? )? const $const_param:ident: $const_ty:ty , $($rem:tt)*)
581    ) => (
582        $crate::__impl_panicfmt_step_aaa_const!{
583            $fixed
584            ($(ignore $(($($const_def)*))? )?)
585            $prev_params
586            ($const_param: $const_ty)
587            ($($rem)*)
588        }
589    );
590    (
591        $fixed:tt
592        $prev_params:tt
593        ($(,)? $(ignore $(($($const_def:tt)*))? )? const $const_param:ident: $const_ty:ty > $($rem:tt)*)
594    ) => (
595        $crate::__impl_panicfmt_step_aaa_const!{
596            $fixed
597            ($(ignore $(($($const_def)*))? )?)
598            $prev_params
599            ($const_param: $const_ty)
600            (> $($rem)*)
601        }
602    );
603    (
604        $fixed:tt
605        ($($prev_params:tt)*)
606        ($(,)? ignore $(($ignore_ty:ty))? $type_param:ident $($rem:tt)*)
607    ) => (
608        $crate::__impl_panicfmt_step_aaa!{
609            $fixed
610            ($($prev_params)* ($type_param ($type_param) ignore (($($ignore_ty)?)) ) )
611            ($($rem)*)
612        }
613    );
614    (
615        $fixed:tt
616        ($($prev_params:tt)*)
617        ($(,)? $type_param:ident $($rem:tt)*)
618    ) => (
619        $crate::__impl_panicfmt_step_aaa!{
620            $fixed
621            (kept_type[$type_param] $($prev_params)* ($type_param ($type_param) kept ()) )
622            ($($rem)*)
623        }
624    );
625    (
626        $fixed:tt
627        $prev_params:tt
628        ($($rem:tt)+)
629    ) => (
630        $crate::__::compile_error!{concat!(
631            "could not parse this in the generic parameter(s) of the type definition:",
632            stringify!($($rem:tt)+)
633        )}
634    );
635}
636
637#[doc(hidden)]
638#[macro_export]
639macro_rules!  __impl_panicfmt_step_aaa_const {
640    (
641        $fixed:tt
642        (ignore($const_def:expr))
643        ($($prev_params:tt)*)
644        ($const_param:ident: $const_ty:ty)
645        $rem:tt
646    ) => {
647        $crate::__impl_panicfmt_step_aaa!{
648            $fixed
649            (
650                $($prev_params)*
651                (
652                    $const_param
653                    (const $const_param: $const_ty)
654                    ignore ({$const_def})
655                )
656            )
657            $rem
658        }
659    };
660    (
661        $fixed:tt
662        ($(ignore)?)
663        ($($prev_params:tt)*)
664        ($const_param:ident: $const_ty:ty)
665        $rem:tt
666    ) => {
667        $crate::__impl_panicfmt_step_aaa!{
668            $fixed
669            (
670                $($prev_params)*
671                (
672                    $const_param
673                    (const $const_param: $const_ty)
674                    ignore ({$crate::__::ConstDefault::DEFAULT})
675                )
676            )
677            $rem
678        }
679    };
680}
681
682#[doc(hidden)]
683#[macro_export]
684macro_rules!  __impl_panicfmt_step_ccc {
685    (
686        $kept:tt
687        $prev_variants:tt
688        [
689            $variant:ident
690            $($(@$is_brace:tt@)? {$($br_field:ident: $br_ty:ty),* $(,)*})?
691            $($(@$is_tuple:tt@)? ( $($tup_ty:ty),* $(,)* ))?
692            $(,$($rem_variants:tt)*)?
693        ]
694    ) => {
695        $crate::zip_counter_and_last!{
696            $crate::__impl_panicfmt_step_ccc_inner!{
697                $kept
698                $prev_variants
699                $variant
700                (
701                    $($($is_brace)? Braced)?
702                    $($($is_tuple)? Tupled)?
703                    Braced
704                )
705                [$($($rem_variants)*)?]
706            }
707            ($($(($br_field, $br_ty))*)? $($((, $tup_ty))*)?)
708            (
709                (0 fi0) (1 fi1) (2 fi2) (3 fi3) (4 fi4) (5 fi5) (6 fi6) (7 fi7)
710                (8 fi8) (9 fi9) (10 fi10) (11 fi11) (12 fi12) (13 fi13) (14 fi14) (15 fi15)
711                (16 fi16) (17 fi17) (18 fi18) (19 fi19) (20 fi20) (21 fi21) (22 fi22) (23 fi23)
712                (24 fi24) (25 fi25) (26 fi26) (27 fi27) (28 fi28) (29 fi29) (30 fi30) (31 fi31)
713                (32 fi32) (33 fi33) (34 fi34) (35 fi35) (36 fi36) (37 fi37) (38 fi38) (39 fi39)
714                (40 fi40) (41 fi41) (42 fi42) (43 fi43) (44 fi44) (45 fi45) (46 fi46) (47 fi47)
715                (48 fi48) (49 fi49) (50 fi50) (51 fi51) (52 fi52) (53 fi53) (54 fi54) (55 fi55)
716                (56 fi56) (57 fi57) (58 fi58) (59 fi59) (60 fi60) (61 fi61) (62 fi62) (63 fi63)
717            )
718        }
719    };
720    // Parsing unit variants / structs
721    (
722        $kept:tt
723        [$($prev_variants:tt)*]
724        [
725            $variant:ident
726            $(, $($rem_variants:tt)*)?
727        ]
728    ) => {
729        $crate::__impl_panicfmt_step_ccc!{
730            $kept
731            [$($prev_variants)* ($variant Braced) ]
732            [$($($rem_variants)*)?]
733        }
734    };
735    // Finished parsing variants/structs,
736    //
737    (
738        $kept:tt
739        $variants:tt
740        []
741    ) => {
742        $crate::__impl_panicfmt_step__panicfmt_impl!{
743            $kept
744            variants $variants
745
746            $kept
747            $variants
748        }
749    };
750}
751
752#[doc(hidden)]
753#[macro_export]
754macro_rules!  __impl_panicfmt_step_ccc_inner {
755    (
756        $kept:tt
757        [$($prev_variants:tt)*]
758        $variant:ident
759        ($delim:ident $($ignore0:tt)*)
760        [$($rem_variants:tt)*]
761
762        $(prefix (($($p_fname:ident)?, $p_ty:ty) ($p_index:tt $p_fi_index:tt)))*
763        $(last (($($l_fname:ident)?, $l_ty:ty) ($l_index:tt $l_fi_index:tt)) )?
764    ) => {
765        $crate::__impl_panicfmt_step_ccc!{
766            $kept
767            [
768                $($prev_variants)*
769                (
770                    $variant
771                    $delim
772                    ($($l_index + 1,)? 0,)
773                    =>
774                    $(prefix (($($p_fname)? $p_index), ($($p_fname)? $p_fi_index), $p_ty))*
775                    $(last (($($l_fname)? $l_index), ($($l_fname)? $l_fi_index), $l_ty))?
776                )
777            ]
778            [$($rem_variants)*]
779        }
780    };
781}
782
783#[doc(hidden)]
784#[macro_export]
785macro_rules!  __impl_panicfmt_step__panicfmt_impl {
786    (
787
788        [
789            $(#[pfmt(display_fmt = $__display_fmt:expr)])?
790            $(#[pfmt(panicvals_lower_bound = $panicvals_lower_bound:expr)])?
791            $type_kind:ident $type_name:ident
792            (
793                $($kept_type:ident [$kept_type_:ident])*
794                $((
795                    $gp_arg:tt
796                    ($($gp_param:tt)*)
797                    $ignorance:tt
798                    ($($gp_arg_concrete:tt)*)
799                ))*
800            )
801            ($($where_preds:tt)*)
802
803            $($to_panicval_impls:tt)*
804        ]
805
806        variants[$(
807            (
808                $variant:ident
809                $delimiter:ident
810                ($field_amount:expr, $($ignore2:tt)*)
811                =>
812                $(
813                    $is_last_field:ident
814                    (
815                        ($fpati:tt $($ignore3:tt)?),
816                        ($fname:tt $($ignore4:tt)?),
817                        $ty:ty
818                    )
819                )*
820            )
821        )*]
822
823        $kept:tt
824        $variants:tt
825    ) => (
826        impl<$($($gp_param)*),*> $crate::PanicFmt for $type_name<$($gp_arg),*>
827        where
828            $($kept_type_: $crate::PanicFmt,)*
829            $($where_preds)*
830        {
831            type This = Self;
832            type Kind = $crate::fmt::IsCustomType;
833
834            const PV_COUNT: $crate::__::usize = $crate::utils::slice_max_usize(&[
835                $(
836                    $crate::fmt::ComputePvCount{
837                        field_amount: $field_amount,
838                        summed_pv_count: 0 $( + <$ty as $crate::PanicFmt>::PV_COUNT )*,
839                        delimiter: $crate::fmt::TypeDelim::$delimiter
840                    }.call(),
841                )*
842                $($panicvals_lower_bound)?
843            ]);
844        }
845
846        macro_rules! __assert_type_name__ {
847            ($type_name) => ()
848        }
849
850        $crate::__impl_to_panicvals!{
851            [$($kept_type)*]
852            [$($ignorance ($($gp_arg_concrete)*))*]
853            [
854                $type_name
855                [$($where_preds)*]
856                $((
857                    ($($gp_param)*)
858                    $gp_arg
859                ))*
860            ]
861            [$($to_panicval_impls)*]
862            $kept
863            $variants
864        }
865    );
866}
867
868#[doc(hidden)]
869#[macro_export]
870macro_rules! __impl_to_panicvals {
871    (
872        [$(kept_type)*]
873        $ignorances:tt
874        $gp_param:tt
875        [$($to_panicval_impls:tt)+]
876        $kept:tt
877        $variants:tt
878    ) => (
879        $(
880            $crate::__impl_to_panicvals_step_aaa!{
881                $ignorances
882                $to_panicval_impls
883                $to_panicval_impls
884                $kept
885                $variants
886            }
887        )*
888    );
889    (
890        []
891        $ignorances:tt
892        [$type_name:ident [$($where_preds:tt)*] $(( ($($gp_param:tt)*) $gp_arg:tt ))* ]
893        []
894        $kept:tt
895        $variants:tt
896    ) => (
897        $crate::__impl_to_panicvals_step_aaa!{
898            $ignorances
899            (
900                impl[$($($gp_param)*),*] $type_name<$($gp_arg),*>
901                where[$($where_preds)*]
902            )
903            (
904                impl[$($($gp_param)*),*] $type_name<$($gp_arg),*>
905                where[$($where_preds)*]
906            )
907            $kept
908            $variants
909        }
910    );
911    ([$(kept_type)+] $ignorances:tt $gp_param:tt [] $kept:tt $variants:tt) => (
912        $crate::__::compile_error!{"\
913            type parameters must either be:\n\
914            - all prefixed with ignore\n\
915            - be replaced with concrete type arguments in \
916            `(impl Foo<Bar>)`s after the type definition\n\
917        "}
918    );
919}
920
921#[doc(hidden)]
922#[macro_export]
923macro_rules! __impl_to_panicvals_step_aaa {
924    (
925        $ignorances:tt
926        (impl $([$($impl_param:tt)*])? $type_name:ident $(where $where_preds:tt)?)
927        $impl:tt
928        $kept:tt
929        $variants:tt
930    ) => {
931        __assert_type_name__!{$type_name}
932
933        $crate::__impl_to_panicvals_step_bbb!{
934            ([$($($impl_param)*)?] $type_name $kept $variants)
935            $ignorances
936            []
937            [> $(where $where_preds)?]
938        }
939    };
940    (
941        $ignorances:tt
942        (impl $([$($impl_param:tt)*])? $type_name:ident <$($args:tt)*)
943        (impl $([$($impl_paramb:tt)*])? $type:path $(where $where_preds:tt)? )
944        $kept:tt
945        $variants:tt
946    ) => {
947        __assert_type_name__!{$type_name}
948
949        $crate::__impl_to_panicvals_step_bbb!{
950            ([$($($impl_param)*)?] $type $kept $variants)
951            $ignorances
952            []
953            [$($args)*]
954        }
955    };
956}
957
958#[doc(hidden)]
959#[macro_export]
960macro_rules! __impl_to_panicvals_step_bbb {
961    // finished parsing
962    (
963        $kept:tt
964        []
965        $cself:tt
966        [> $(where[$($where_preds:tt)*])?]
967    ) => {
968        $crate::__impl_to_panicvals_finish!{
969            $kept
970            [$($($where_preds)*)?]
971            $cself
972        }
973    };
974
975
976
977    // const or lifetime argument
978    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $gen_arg:tt , $($rem:tt)*]) => {
979        $crate::__impl_to_panicvals_step_bbb_inner!{
980            $kept
981            $ignorance
982            [$gen_arg]
983            $prev_cself
984            [$($rem)*]
985        }
986    };
987    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $gen_arg:tt > $($rem:tt)*]) => {
988        $crate::__impl_to_panicvals_step_bbb_inner!{
989            $kept
990            $ignorance
991            [$gen_arg]
992            $prev_cself
993            [> $($rem)*]
994        }
995    };
996
997    // type argument
998    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $ty_arg:ty , $($rem:tt)* ]) => {
999        $crate::__impl_to_panicvals_step_bbb_inner!{
1000            $kept
1001            $ignorance
1002            [$ty_arg]
1003            $prev_cself
1004            [$($rem)*]
1005        }
1006    };
1007    ($kept:tt $ignorance:tt $prev_cself:tt [$(,)? $ty_arg:ty > $($rem:tt)*]) => {
1008        $crate::__impl_to_panicvals_step_bbb_inner!{
1009            $kept
1010            $ignorance
1011            [$ty_arg]
1012            $prev_cself
1013            [> $($rem)*]
1014        }
1015    };
1016}
1017
1018#[doc(hidden)]
1019#[macro_export]
1020macro_rules! __impl_to_panicvals_step_bbb_inner {
1021    (
1022        $kept:tt
1023        [kept $gp_arg_concrete:tt $($rem_ignorance:tt)*]
1024        [$gen_arg:tt]
1025        [$($prev_cself:tt)*]
1026        $rem:tt
1027    ) => {
1028        $crate::__impl_to_panicvals_step_bbb!{
1029            $kept
1030            [$($rem_ignorance)*]
1031            [$($prev_cself)* $gen_arg,]
1032            $rem
1033        }
1034    };
1035    (
1036        $kept:tt
1037        [ignore ($($gp_arg_concrete:tt)*) $($rem_ignorance:tt)*]
1038        $gen_arg:tt
1039        [$($prev_cself:tt)*]
1040        $rem:tt
1041    ) => {
1042        $crate::__impl_to_panicvals_step_bbb!{
1043            $kept
1044            [$($rem_ignorance)*]
1045            [$($prev_cself)* $($gp_arg_concrete)*,]
1046            $rem
1047        }
1048    };
1049}
1050
1051#[doc(hidden)]
1052#[macro_export]
1053macro_rules! __impl_to_panicvals_finish {
1054    // finished parsing
1055    (
1056        (
1057            [$($impl_param:tt)*]
1058            $type:ty
1059
1060            [
1061                $(#[pfmt(display_fmt = $display_fmt:expr)])?
1062                $(#[pfmt(panicvals_lower_bound = $__panicvals_lower_bound:expr)])?
1063                $type_kind:ident $type_name:ident
1064                $generics:tt
1065                $type_where_preds:tt
1066
1067                $($to_panicval_impls:tt)*
1068            ]
1069
1070            [$(
1071                (
1072                    $variant:ident
1073                    $delimiter:ident
1074                    ($field_amount:expr, $($ignore2:tt)*)
1075                    =>
1076                    $(
1077                        $is_last_field:ident
1078                        (
1079                            ($fpati:tt $($ignore3:tt)?),
1080                            ($fname:tt $($ignore4:tt)?),
1081                            $ty:ty
1082                        )
1083                    )*
1084                )
1085            )*]
1086
1087        )
1088        [ $($where_preds:tt)* ]
1089        $cself:tt
1090    ) => {
1091        /// Provides the required `to_panicvals` method for
1092        /// [`const_panic::fmt::PanicFmt` trait](trait@__cp_bCj7dq3Pud::fmt::PanicFmt)
1093        impl<$($impl_param)*> $type
1094        where
1095            $($where_preds)*
1096        {
1097            /// Gets the `PanicVal`s for
1098            /// [`const_panic`](__cp_bCj7dq3Pud)-based
1099            /// formatting of this value.
1100            pub const fn to_panicvals(
1101                &self,
1102                mut fmt: $crate::FmtArg,
1103            ) -> [$crate::PanicVal<'_>; $crate::__ipm_cself!($type_name $cself)] {
1104                $(
1105                    if let $crate::fmt::FmtKind::Display = fmt.fmt_kind {
1106                        $display_fmt(self, fmt)
1107                    } else
1108                )? {
1109                    match self {
1110                        $(
1111                            $crate::__ipm_pattern!($type_kind $variant{$($fpati: $fname,)* ..}) =>
1112                                $crate::__ipm_fmt!{
1113                                    ($crate::__ipm_cself!($type_name $cself))
1114                                    $delimiter
1115                                    $variant
1116                                    fmt
1117                                    ( $($is_last_field ($fname, $ty))* )
1118                                },
1119                        )*
1120                    }
1121                }
1122            }
1123        }
1124    };
1125}
1126
1127#[doc(hidden)]
1128#[macro_export]
1129macro_rules!  __ipm_pattern {
1130    (struct $name:ident {$($patterns:tt)*}) => {
1131        $name {$($patterns)*}
1132    };
1133    (enum $name:ident {$($patterns:tt)*}) => {
1134        Self::$name {$($patterns)*}
1135    };
1136}
1137
1138#[doc(hidden)]
1139#[macro_export]
1140macro_rules!  __ipm_fmt {
1141    (
1142        ($count:expr) $delimiter:ident $typename:ident $fmt:ident
1143        ( $($is_last_field:ident ($fname:ident, $ty:ty))+ )
1144    ) => ({
1145        let (open, close) = $crate::fmt::TypeDelim::$delimiter.get_open_and_close();
1146
1147        $crate::__::flatten_panicvals::<{$count}>(&[
1148            &[
1149                $crate::PanicVal::write_str($crate::__::stringify!($typename)),
1150                {
1151                    $fmt = $fmt.indent();
1152                    open.to_panicval($fmt)
1153                }
1154            ],
1155            $(
1156                $crate::__ipm_pv_fmt_field_name!($delimiter $fname),
1157                &$crate::PanicFmt::PROOF
1158                    .infer($fname)
1159                    .coerce($fname)
1160                    .to_panicvals($fmt),
1161                &$crate::__ipm_pv_comma!($is_last_field)
1162                    .to_panicvals($fmt),
1163            )*
1164            &[
1165                {
1166                    $fmt = $fmt.unindent();
1167                    close.to_panicval($fmt)
1168                }
1169            ],
1170        ])
1171    });
1172    (
1173        ($count:expr) $delimiter:ident $typename:ident $fmt:ident
1174        ()
1175    ) => {
1176        $crate::__::flatten_panicvals::<{$count}>(&[
1177            &[$crate::PanicVal::write_str($crate::__::stringify!($typename))]
1178        ])
1179    }
1180}
1181
1182#[doc(hidden)]
1183#[macro_export]
1184macro_rules! __ipm_pv_fmt_field_name {
1185    (Tupled $field_name:ident) => {
1186        &[]
1187    };
1188    (Braced $field_name:ident) => {
1189        &[$crate::PanicVal::write_str($crate::__::concat!(
1190            $crate::__::stringify!($field_name),
1191            ": "
1192        ))]
1193    };
1194}
1195
1196#[doc(hidden)]
1197#[macro_export]
1198macro_rules! __ipm_pv_comma {
1199    (prefix) => {
1200        $crate::fmt::COMMA_SEP
1201    };
1202    (last) => {
1203        $crate::fmt::COMMA_TERM
1204    };
1205}
1206
1207#[doc(hidden)]
1208#[macro_export]
1209macro_rules! __ipm_cself {
1210    ($type_name:ident [$($cself:tt)*]) => {
1211        <$type_name<$($cself)*> as $crate::PanicFmt>::PV_COUNT
1212    };
1213}