flex_error/
macros.rs

1pub use paste::paste;
2
3/**
4  `define_error!` is the main macro that implements a mini DSL to
5  define error types using `flex-error`. The DSL syntax
6  is as follows:
7
8  ```ignore
9  define_error! {
10    ErrorName {
11      SubErrorWithFieldsAndErrorSource
12        { field1: Type1, field2: Type2, ... }
13        [ ErrorSource ]
14        | e | { format_args!(
15          "format error message with field1: {}, field2: {}, source: {}",
16          e.field1, e.field2, e.source)
17        },
18      SubErrorWithFieldsOnly
19        { field1: Type1, field2: Type2, ... }
20        | e | { format_args!(
21          "format error message with field1: {}, field2: {}",
22          e.field1, e.field2)
23        },
24      SubErrorWithSourceOnly
25        [ ErrorSource ]
26        | e | { format_args!(
27          "format error message with source: {}",
28          e.source)
29        },
30      SubError
31        | e | { format_args!(
32          "only suberror message")
33        },
34    }
35  }
36  ```
37
38  ## Macro Expansion
39
40  Behind the scene, for an error named `MyError`, `define_error!`
41  does the following:
42
43    - Define a struct in the form
44
45      ```ignore
46      pub struct MyError(pub MyErrorDetail, pub flex_error::DefaultTracer)
47      ```
48
49    - Define an enum in the form
50
51      ```ignore
52      pub enum MyError { ... }
53      ```
54
55      For each suberror named `MySubError`, does the following:
56
57        - Define a variant in `MyError` in the form
58          ```ignore
59          pub enum MyError { ..., MySubError(MySubErrorSubdetail) ,... }
60          ```
61
62          - Implement [`core::fmt::Debug`] and [`core::fmt::Display`]
63            for `MyError`.
64
65          - If the `"std"` feature is enabled on the `flex-error` crate,
66            it will generate an `impl` block for [`std::error::Error`].
67
68          - Implement [`ErrorSource<DefaultTracer>`](crate::ErrorSource)
69            for `MyError`, with `MyErrorDetail` being the `Detail` type,
70            and `MyError` being the `Source` type.
71
72          - Implement the following helper methods in `impl MyError {...}`:
73
74            - `pub fn detail(&self) -> &MyErrorDetail`
75
76            - `pub fn trace(&self) -> flex_error::DefaultTracer`
77
78            - `pub fn add_trace<E: Display>(self, e: &E) -> MyError`
79
80        - Define a struct in the form
81
82          ```ignore
83          pub struct MySubErrorSubdetail { ... }
84          ```
85
86          - For each field named `my_field: MyFieldType`, define a struct
87            field in the form
88
89            ```ignore
90            struct MySubErrorSubdetail { ..., pub my_field: MyFieldType, ... }
91            ```
92
93          - If the sub-error has an error source `MySource` implementing
94            [`ErrorSource<DefaultTracer>`](crate::ErrorSource), define a `source` field
95            in the form
96
97            ```ignore
98            struct MySubErrorSubdetail { ..., pub source: MySource::Detail }
99            ```
100
101          - Implement [`core::fmt::Display`] in the form
102
103            ```ignore
104            impl Display for MySubErrorSubdetail { ... }
105            ```
106
107        - Define a snake-cased error constructor method in `MyError` in the form
108
109          ```ignore
110          impl MyError { pub fn my_sub_error(...) -> MyError { ... } }
111          ```
112
113          - For each field named `my_field: MyFieldType`, define a
114            function argument in the form
115
116            ```ignore
117            fn my_sub_error(..., my_field: MyFieldType, ...)
118            ```
119
120          - If the sub-error has an error source `MySource` implementing
121            [`ErrorSource`](crate::ErrorSource), define a `source` field in the form
122
123            ```ignore
124            fn my_sub_error(..., source: MySource::Detail)
125            ```
126
127  ## Formatter
128
129  For each sub-error definition, a formatter needs to be provided using the
130  closure syntax. For example, the following definition:
131
132
133  ```ignore
134  MyError {
135    MySubError
136      { code: u32 }
137      [ MySource ]
138      | e | { format_args!("error with code {}", e.code) },
139    ...
140  }
141  ```
142
143  will include the following expansion:
144
145  ```
146  impl ::core::fmt::Display for MySubErrorSubdetail {
147    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
148      let e = self;
149      write!(f, "{}", format_args!("error with code {}", e.code))
150    }
151  }
152  ```
153
154  Note that there is no need to manually display the error source, as the
155  source is already automatically traced by the error tracer.
156
157  If a sub-error do not have any field, we can write a simpler form of the
158  formatter like:
159
160  ```ignore
161  MyError {
162    MySubError
163      | _ | { "something went wrong" },
164    ...
165  }
166  ```
167
168  ## Example Definition
169
170  We can demonstrate the macro expansion of `define_error!` with the following example:
171
172  ```ignore
173  // An external error type implementing Display
174  use external_crate::ExternalError;
175
176  define_error! {
177    FooError {
178      Bar
179        { code: u32 }
180        [ DisplayError<ExternalError> ]
181        | e | { format_args!("Bar error with code {}", e.code) },
182      Baz
183        { extra: String }
184        | e | { format_args!("General Baz error with extra detail: {}", e.extra) }
185    }
186  }
187  ```
188
189  The above code will be expanded into something like follows:
190
191  ```ignore
192  pub struct FooError(pub FooErrorDetail, pub flex_error::DefaultTracer);
193
194  #[derive(Debug)]
195  pub enum FooErrorDetail {
196      Bar(BarSubdetail),
197      Baz(BazSubdetail),
198  }
199
200  #[derive(Debug)]
201  pub struct BarSubdetail {
202      pub code: u32,
203      pub source: ExternalError
204  }
205
206  #[derive(Debug)]
207  pub struct BazSubdetail {
208      pub extra: String
209  }
210
211  fn bar_error(code: u32, source: ExternalError) -> FooError { ... }
212  fn baz_error(extra: String) -> FooError { ... }
213
214  impl ::core::fmt::Display for BarSubdetail {
215    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
216      let e = self;
217      write!(f, "{}", format_args!("Bar error with code {}", e.code))
218    }
219  }
220
221  impl ::core::fmt::Display for BazSubdetail {
222    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
223      let e = self;
224      write!(f, "{}", format_args!("General Baz error with extra detail: {}", e.code))
225    }
226  }
227
228  impl Display for FooErrorDetail { ... }
229  ```
230
231  For the detailed macro expansion, you can use [cargo-expand](https://github.com/dtolnay/cargo-expand)
232  to expand the Rust module that uses `define_error!` to see how the error definition
233  gets expanded.
234
235  Since `FooError` implements [`ErrorSource`](crate::ErrorSource), it can be used
236  directly as a error source in other error definitions. For example:
237
238  ```ignore
239  define_error! {
240    QuuxError {
241      Foo
242        { action: String }
243        [ FooError ]
244        | e | { format_args!("error arised from Foo when performing action {}", e.action) },
245      ...
246    }
247  }
248  ```
249
250  Would be expanded to include the following definitions:
251
252  ```ignore
253  pub struct FooSubdetail {
254    pub action: String,
255    pub source: FooErrorDetail
256  }
257
258  pub fn foo_error(action: String, source: FooError) { ... }
259  ```
260
261  In the formatter for `QuuxErrorDetail::Foo`, we can also see that it does not
262  need to include the error string from `FooError`. This is because the error
263  tracer already takes care of the source error trace, so the full trace is
264  automatically tracked inside `foo_error`. The outer error only need to
265  add additional detail about what caused the source error to be raised.
266
267  ## Attributes
268
269  `define_error!` supports adding attributes to the generated error types.
270
271  ### First `doc` Attribute
272
273  If the first attribute is a [`doc`](https://doc.rust-lang.org/rustdoc/the-doc-attribute.html)
274  attribute, it is attached to the main error struct. For example:
275
276  ```ignore
277  define_error! {
278    /// Documentation for MyError
279    MyError { ... }
280  }
281  ```
282
283  will include the following expansion:
284
285  ```ignore
286  #[doc = "Documentation for MyError"]
287  pub struct MyError(pub MyErrorDetail, pub flex_error::DefaultTracer);
288  ```
289
290  ## Common Attributes
291
292  For all other attributes defined on the main error type,
293  they are defined on the _error detail_ and _sub-errors type. For example:
294
295
296  ```ignore
297  define_error! {
298    #[derive(Debug, Clone)]
299    MyError {
300      Foo
301        { ... }
302        | _ | { "foo error" },
303
304      Bar
305        { ... }
306        | _ | { "bar error" },
307    }
308  }
309  ```
310
311  will include the following expansion:
312
313  ```ignore
314  pub struct MyError(pub MyErrorDetail, pub flex_error::DefaultTracer);
315
316  #[derive(Debug, Clone)]
317  pub enum MyErrorDetail { ... }
318
319  #[derive(Debug, Clone)]
320  pub struct FooSubdetail { ... }
321
322  #[derive(Debug, Clone)]
323  pub struct BarSubdetail { ... }
324  ```
325
326  Note that we do not add the `derive` attribute to the main error struct
327  `MyError`. This is because the [`DefaultTracer`](crate::DefaultTracer)
328  type is opaque, and auto deriving traits like `Clone` on it is
329  generally not supported.
330
331  If you need the main error type to implement certain traits,
332  you can instead define your own custom `impl` definition for it.
333
334  ## Sub Attributes
335
336  We can also define custom attributes for only the sub-error.
337  In that case, the attribute is given to the sub-detail type.
338  For example:
339
340  ```ignore
341  define_error! {
342    MyError {
343      /// Documentation for Foo
344      #[derive(Clone)]
345      Foo
346        { ... }
347        | _ | { "foo error" },
348
349      ...
350    }
351  }
352  ```
353
354  will include the following expansion:
355
356  ```ignore
357  #[doc = "Documentation for Foo"]
358  #[derive(Clone)]
359  pub struct FooSubdetail { ... }
360  ```
361
362  Note that if no attribute is given to the main error,
363  the `#[derive(Debug)]` trait is added by default.
364  So there is no need to derive it again in the
365  sub-errors.
366
367**/
368
369#[macro_export]
370macro_rules! define_error {
371  ( $name:ident
372    { $($suberrors:tt)* }
373  ) => {
374    $crate::define_error_with_tracer![
375      @tracer( $crate::DefaultTracer ),
376      @attr[ derive(Debug) ],
377      @name( $name ),
378      @suberrors{ $($suberrors)* }
379    ];
380  };
381  ( #[doc = $doc:literal] $( #[$attr:meta] )*
382    $name:ident
383    { $($suberrors:tt)* }
384  ) => {
385    $crate::define_error_with_tracer![
386      @tracer( $crate::DefaultTracer ),
387      @doc( $doc ),
388      @attr[ $( $attr ),* ],
389      @name( $name ),
390      @suberrors{ $($suberrors)* }
391    ];
392  };
393  ( $( #[$attr:meta] )*
394    $name:ident
395    { $($suberrors:tt)* }
396  ) => {
397    $crate::define_error_with_tracer![
398      @tracer( $crate::DefaultTracer ),
399      @attr[ $( $attr ),* ],
400      @name( $name ),
401      @suberrors{ $($suberrors)* }
402    ];
403  };
404  ( @with_tracer[ $tracer:ty ]
405    $name:ident,
406    { $($suberrors:tt)* }
407  ) => {
408    $crate::define_error_with_tracer![
409      @tracer( $tracer ),
410      @attr[ derive(Debug) ],
411      @name( $name ),
412      @suberrors{ $($suberrors)* }
413    ];
414  };
415  ( @with_tracer[ $tracer:ty ]
416    $( #[$attr:meta] )*
417    $name:ident,
418    @suberrors{ $($suberrors:tt)* }
419  ) => {
420    $crate::define_error_with_tracer![
421      @tracer( $tracer ),
422      @attr[ $( $attr ),* ],
423      @name( $name ),
424      @suberrors{ $($suberrors)* }
425    ];
426  };
427}
428
429/// This macro allows error types to be defined with custom error tracer types
430/// other than [`DefaultTracer`](crate::DefaultTracer). Behind the scene,
431/// a macro call to `define_error!{ ... } really expands to
432/// `define_error_with_tracer!{ flex_error::DefaultTracer; ... }`
433#[macro_export]
434#[doc(hidden)]
435macro_rules! define_error_with_tracer {
436  ( @tracer( $tracer:ty ),
437    $( @doc($doc:literal), )?
438    @attr[ $( $attr:meta ),* ],
439    @name($name:ident),
440    @suberrors{ $($suberrors:tt)* } $(,)?
441  ) => {
442    $crate::macros::paste![
443      $crate::define_main_error!(
444        @tracer( $tracer ),
445        $( @doc( $doc ), )?
446        @name( $name )
447      );
448
449      $crate::define_error_detail!(
450        @attr[ $( $attr ),* ] ,
451        @name( $name ),
452        @suberrors{ $($suberrors)* });
453
454      $crate::define_suberrors! {
455        @tracer($tracer),
456        @attr[ $( $attr ),* ],
457        @name($name),
458        { $( $suberrors )* }
459      }
460    ];
461  };
462}
463
464#[macro_export]
465#[doc(hidden)]
466macro_rules! define_main_error {
467  ( @tracer( $tracer:ty ),
468    $( @doc( $doc:literal ), )?
469    @name( $name:ident ) $(,)?
470  ) => {
471    $crate::macros::paste![
472      $crate::define_main_error_struct!(
473        @tracer( $tracer ),
474        $( @doc($doc), )?
475        @name( $name )
476      );
477
478      impl $crate::ErrorSource<$tracer> for $name {
479        type Source = Self;
480        type Detail = [< $name Detail >];
481
482        fn error_details($name(detail, trace): Self) -> ([< $name Detail >], Option<$tracer>) {
483            (detail, Some(trace))
484        }
485      }
486
487      impl ::core::fmt::Debug for $name
488      where
489          $tracer: ::core::fmt::Debug,
490      {
491          fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
492              ::core::fmt::Debug::fmt(self.trace(), f)
493          }
494      }
495
496      impl ::core::fmt::Display for $name
497      where
498          $tracer: ::core::fmt::Debug,
499      {
500          fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
501            -> ::core::fmt::Result
502          {
503              // Always use `Debug` to format error traces, as eyre do not
504              // include full back trace information in normal Display mode.
505              ::core::fmt::Debug::fmt(self.trace(), f)
506          }
507      }
508
509      $crate::define_std_err_impl!(
510        @tracer( $tracer ),
511        @name( $name )
512      );
513
514      impl $name {
515        pub fn detail(&self) -> &[< $name Detail >] {
516            &self.0
517        }
518
519
520        pub fn into_detail(self) -> [< $name Detail >] {
521            self.0
522        }
523
524        pub fn trace(&self) -> &$tracer {
525            &self.1
526        }
527
528        pub fn into_trace(self) -> $tracer {
529            self.1
530        }
531
532        pub fn add_trace<E: ::core::fmt::Display>(self, message: &E) -> Self
533        where
534            $tracer: $crate::ErrorMessageTracer,
535        {
536            let detail = self.0;
537            let trace = $crate::ErrorMessageTracer::add_message(self.1, message);
538            $name(detail, trace)
539        }
540
541        pub fn trace_from<E, Cont>(source: E::Source, cont: Cont) -> Self
542        where
543            E: $crate::ErrorSource<$tracer>,
544            $tracer: $crate::ErrorMessageTracer,
545            Cont: FnOnce(E::Detail) -> [< $name Detail >],
546        {
547            let (detail1, m_trace1) = E::error_details(source);
548            let detail2 = cont(detail1);
549            match m_trace1 {
550                Some(trace1) => {
551                    let trace2 = $crate::ErrorMessageTracer::add_message(trace1, &detail2);
552                    $name(detail2, trace2)
553                }
554                None => {
555                    let trace2 = $crate::ErrorMessageTracer::new_message(&detail2);
556                    $name(detail2, trace2)
557                }
558            }
559        }
560      }
561    ];
562  }
563}
564
565// define the impl for `std::error::Error` only in std mode
566#[cfg(feature = "std")]
567#[macro_export]
568#[doc(hidden)]
569macro_rules! define_std_err_impl {
570  ( @tracer( $tracer:ty ),
571    @name( $name:ident ) $(,)?
572  ) => {
573    $crate::macros::paste![
574      impl $crate::StdError for $name
575      where
576          [< $name Detail >]: ::core::fmt::Display,
577          $tracer: ::core::fmt::Debug + ::core::fmt::Display,
578          $tracer: $crate::ErrorMessageTracer,
579      {
580          fn source(&self) -> ::core::option::Option<&(dyn $crate::StdError + 'static)> {
581              $crate::ErrorMessageTracer::as_error(self.trace())
582          }
583      }
584    ];
585  }
586}
587
588// do not define the impl for `std::error::Error` when in no_std mode
589#[cfg(not(feature = "std"))]
590#[macro_export]
591#[doc(hidden)]
592macro_rules! define_std_err_impl {
593    ( @tracer( $tracer:ty ),
594    @name( $name:ident ) $(,)?
595  ) => {};
596}
597
598#[macro_export]
599#[doc(hidden)]
600macro_rules! define_main_error_struct {
601  ( @tracer( $tracer:ty ),
602    $( @doc( $doc:literal ), )?
603    @name( $name:ident ) $(,)?
604  ) => {
605    $crate::macros::paste![
606      $( #[doc = $doc] )?
607      pub struct $name (pub [< $name Detail >], pub $tracer);
608    ];
609  }
610}
611
612#[macro_export]
613#[doc(hidden)]
614macro_rules! with_suberrors {
615  ( @cont($cont:path),
616    @ctx[ $($args:tt)* ],
617    @suberrors{
618      $(
619        $( #[$sub_attr:meta] )*
620        $suberror:ident
621        $( { $( $arg_name:ident : $arg_type:ty ),* $(,)? } )?
622        $( [ $source:ty ] )?
623        | $formatter_arg:pat | $formatter:expr
624      ),* $(,)?
625    } $(,)?
626  ) => {
627    $cont!( @ctx[ $( $args )* ], @suberrors{ $( $suberror ),* } );
628  }
629}
630
631#[macro_export]
632#[doc(hidden)]
633macro_rules! define_error_detail {
634  ( @attr[ $( $attr:meta ),* ],
635    @name( $name:ident ),
636    @suberrors{ $($suberrors:tt)* } $(,)?
637  ) => {
638    $crate::with_suberrors!(
639      @cont($crate::define_error_detail_enum),
640      @ctx[
641        @attr[ $( $attr ),* ],
642        @name($name)
643      ],
644      @suberrors{ $( $suberrors )* }
645    );
646
647    $crate::with_suberrors!(
648      @cont($crate::define_error_detail_display),
649      @ctx[
650        @name($name)
651      ],
652      @suberrors{ $( $suberrors )* }
653    );
654  }
655}
656
657#[macro_export]
658#[doc(hidden)]
659macro_rules! define_error_detail_enum {
660  ( @ctx[
661      @attr[ $( $attr:meta ),* ],
662      @name($name:ident)
663    ],
664    @suberrors{ $( $suberror:ident ),* } $(,)?
665  ) => {
666    $crate::macros::paste! [
667      $( #[$attr] )*
668      pub enum [< $name Detail >] {
669        $(
670          $suberror (
671            [< $suberror Subdetail >]
672          )
673        ),*
674      }
675    ];
676  }
677}
678
679#[macro_export]
680#[doc(hidden)]
681macro_rules! define_error_detail_display {
682  ( @ctx[
683      @name( $name:ident )
684    ],
685    @suberrors{ $( $suberror:ident ),* } $(,)?
686  ) => {
687    $crate::macros::paste! [
688      impl ::core::fmt::Display for [< $name Detail >] {
689        fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
690          -> ::core::fmt::Result
691        {
692          match self {
693            $(
694              Self::$suberror( suberror ) => {
695                ::core::write!( f, "{}",  suberror )
696              }
697            ),*
698          }
699        }
700      }
701    ];
702  }
703}
704
705#[macro_export]
706#[doc(hidden)]
707macro_rules! define_suberrors {
708  ( @tracer($tracer:ty),
709    @attr[ $( $attr:meta ),* ],
710    @name($name:ident),
711    {} $(,)?
712  ) => { };
713  ( @tracer($tracer:ty),
714    @attr[ $( $attr:meta ),* ],
715    @name($name:ident),
716    {
717      $( #[$sub_attr:meta] )*
718      $suberror:ident
719        $( { $( $arg_name:ident : $arg_type:ty ),* $(,)? } )?
720        $( [ $source:ty ] )?
721        | $formatter_arg:pat | $formatter:expr
722
723      $( , $($tail:tt)* )?
724    }
725  ) => {
726    $crate::macros::paste![
727      $crate::define_suberror! {
728        @tracer( $tracer ),
729        @attr[ $( $attr ),* ],
730        @sub_attr[ $( $sub_attr ),* ],
731        @name( $name ),
732        @suberror( $suberror ),
733        @args( $( $( $arg_name : $arg_type ),* )? )
734        $( @source[ $source ] )?
735      }
736
737      impl ::core::fmt::Display for [< $suberror Subdetail >] {
738        fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
739          use ::core::format_args;
740          let $formatter_arg = self;
741          ::core::write!(f, "{}",  $formatter)
742        }
743      }
744
745      impl $name {
746        $crate::define_error_constructor! {
747          @tracer( $tracer ),
748          @name( $name ),
749          @suberror( $suberror ),
750          @args( $( $( $arg_name : $arg_type ),* )? )
751          $( @source[ $source ] )?
752        }
753      }
754    ];
755
756    $crate::define_suberrors! {
757      @tracer($tracer),
758      @attr[ $( $attr ),* ],
759      @name($name),
760      { $( $( $tail )* )? }
761    }
762  };
763}
764
765/// Internal macro used to define suberror structs
766#[macro_export]
767#[doc(hidden)]
768macro_rules! define_suberror {
769  ( @tracer( $tracer:ty ),
770    @attr[ $( $attr:meta ),* ],
771    @sub_attr[ $( $sub_attr:meta ),* ],
772    @name( $name:ident ),
773    @suberror( $suberror:ident ),
774    @args( $( $arg_name:ident: $arg_type:ty ),* )
775    @source[ Self ]
776  ) => {
777    $crate::macros::paste! [
778      $( #[ $attr ] )*
779      $( #[ $sub_attr ] )*
780      pub struct [< $suberror Subdetail >] {
781        $( pub $arg_name: $arg_type, )*
782        pub source: $crate::alloc::boxed::Box< [< $name Detail >] >
783      }
784    ];
785  };
786  ( @tracer( $tracer:ty ),
787    @attr[ $( $attr:meta ),* ],
788    @sub_attr[ $( $sub_attr:meta ),* ],
789    @name( $name:ident ),
790    @suberror( $suberror:ident ),
791    @args( $( $arg_name:ident: $arg_type:ty ),* )
792    $( @source[ $source:ty ] )?
793  ) => {
794    $crate::macros::paste! [
795      $( #[ $attr ] )*
796      $( #[ $sub_attr ] )*
797      pub struct [< $suberror Subdetail >] {
798        $( pub $arg_name: $arg_type, )*
799        $( pub source: $crate::AsErrorDetail<$source, $tracer> )?
800      }
801    ];
802  };
803}
804
805/// Internal macro used to define suberror constructor functions
806#[macro_export]
807#[doc(hidden)]
808macro_rules! define_error_constructor {
809  ( @tracer( $tracer:ty ),
810    @name( $name:ident ),
811    @suberror( $suberror:ident ),
812    @args( $( $arg_name:ident: $arg_type:ty ),* ) $(,)?
813  ) => {
814    $crate::macros::paste! [
815      pub fn [< $suberror:snake >](
816        $( $arg_name: $arg_type, )*
817      ) -> $name
818      {
819        let detail = [< $name Detail >]::$suberror([< $suberror Subdetail >] {
820          $( $arg_name, )*
821        });
822
823        let trace = < $tracer as $crate::ErrorMessageTracer >::new_message(&detail);
824        $name(detail, trace)
825      }
826    ];
827  };
828  ( @tracer( $tracer:ty ),
829    @name( $name:ident ),
830    @suberror( $suberror:ident ),
831    @args( $( $arg_name:ident: $arg_type:ty ),* )
832    @source[ Self ]
833  ) => {
834    $crate::macros::paste! [
835      pub fn [< $suberror:snake >](
836        $( $arg_name: $arg_type, )*
837        source: $name
838      ) -> $name
839      {
840        let detail = [< $name Detail >]::$suberror([< $suberror Subdetail >] {
841          $( $arg_name, )*
842          source: Box::new(source.0),
843        });
844
845        let trace = source.1.add_message(&detail);
846
847        $name(detail, trace)
848      }
849    ];
850  };
851  ( @tracer( $tracer:ty ),
852    @name( $name:ident ),
853    @suberror( $suberror:ident ),
854    @args( $( $arg_name:ident: $arg_type:ty ),* )
855    @source[ $source:ty ]
856  ) => {
857    $crate::macros::paste! [
858      pub fn [< $suberror:snake >](
859        $( $arg_name: $arg_type, )*
860        source: $crate::AsErrorSource< $source, $tracer >
861      ) -> $name
862      {
863        $name::trace_from::<$source, _>(source,
864          | source_detail | {
865            [< $name Detail >]::$suberror([< $suberror Subdetail >] {
866              $( $arg_name, )*
867              source: source_detail,
868            })
869          })
870      }
871    ];
872  };
873}