generics/
lib.rs

1#![no_std]
2#![deny(warnings)]
3#![doc(test(attr(deny(warnings))))]
4#![doc(test(attr(allow(unknown_lints))))]
5#![doc(test(attr(allow(dead_code))))]
6#![doc(test(attr(allow(unused_imports))))]
7#![doc(test(attr(allow(unused_variables))))]
8#![doc(test(attr(allow(non_local_definitions))))]
9
10#[doc(hidden)]
11pub use core::compile_error as std_compile_error;
12#[doc(hidden)]
13pub use core::concat as std_concat;
14#[doc(hidden)]
15pub use core::stringify as std_stringify;
16
17/// Parses (optional) generics and (optional) subsequent where clause.
18///
19/// This macro accepts an input in the following form:
20///
21/// ```ignore
22/// $callback:path { $($callback_args:tt)* }
23/// $(
24///     <$generics>
25///     $($tokens_between_generics_and_where_clause:tt)*
26///     $(where $where_clause)?
27/// )?
28/// $(
29///     $( ; | { $($body:tt)* } )
30///     $($remaining_tokens:tt)*
31/// )?
32/// ```
33///
34/// and expands into
35///
36/// ```ignore
37/// $callback! {
38///     $($callback_args)*
39///     [ $(<$generics>)? ]
40///     [ $(<$generics_without_constraints>)? ]
41///     [ $($(where $where_clause)?)? ]
42///     $($($tokens_between_generics_and_where_clause)*)?
43///     $(
44///         $( ; | { $($body)* } )
45///         $($remaining_tokens)*
46///     )?
47/// }
48/// ```
49///
50/// # Examples
51///
52/// ```rust
53/// pub trait TheTrait { }
54///
55/// #[doc(hidden)]
56/// pub use generics::parse as generics_parse;
57/// #[doc(hidden)]
58/// pub use std::compile_error as std_compile_error;
59///
60/// #[macro_export]
61/// macro_rules! impl_the_trait {
62///     (
63///         $name:ident $($token:tt)*
64///     ) => {
65///         $crate::generics_parse! {
66///             $crate::impl_the_trait_impl {
67///                 @impl $name
68///             }
69///             $($token)*
70///         }
71///     };
72/// }
73///
74/// #[doc(hidden)]
75/// #[macro_export]
76/// macro_rules! unexpected_token {
77///     () => { };
78/// }
79///
80/// #[doc(hidden)]
81/// #[macro_export]
82/// macro_rules! impl_the_trait_impl {
83///     (
84///         @impl $name:ident [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
85///     ) => {
86///         impl $($g)* $crate::TheTrait for $name $($r)* $($w)* { }
87///     };
88///     (
89///         @impl $name:ident [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $token:tt $($tail:tt)* 
90///     ) => {
91///         $crate::unexpected_token!($token);
92///         $crate::std_compile_error!(
93///             "invalid input, allowed input is '$name:ident $(<$generics> $(where $where_clause)?)?'"
94///         );
95///     };
96/// }
97/// ```
98#[macro_export]
99macro_rules! parse {
100    (
101        $callback:path { $($callback_args:tt)* } < $($token:tt)*
102    ) => {
103        $crate::parse_generics_impl! { [$callback] [$($callback_args)*] [] [] [$($token)*] }
104    };
105    (
106        $callback:path { $($callback_args:tt)* } $($token:tt)*
107    ) => {
108        $crate::deny_where_clause_impl! { [$callback] [$($callback_args)*] [] [$($token)*] }
109    };
110}
111
112#[doc(hidden)]
113#[macro_export]
114macro_rules! unexpected_token {
115    () => { };
116}
117
118#[doc(hidden)]
119#[macro_export]
120macro_rules! parse_generics_impl {
121    (
122        [$callback:path]
123        [$($callback_args:tt)*]
124        [$($g:tt)*]
125        [$($r:tt)*]
126        [$param:ident $($token:tt)*]
127    ) => {
128        $crate::parse_generics_impl! { 
129            @param
130            [$param]
131            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
132            [$($token)*]
133        }
134    };
135    (
136        [$callback:path]
137        [$($callback_args:tt)*]
138        [$($g:tt)*]
139        [$($r:tt)*]
140        [$param:lifetime $($token:tt)*]
141    ) => {
142        $crate::parse_generics_impl! { 
143            @param
144            [$param]
145            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
146            [$($token)*]
147        }
148    };
149    (
150        [$callback:path]
151        [$($callback_args:tt)*]
152        [$($g:tt)*]
153        [$($r:tt)*]
154        [$x:tt $($token:tt)*]
155    ) => {
156        $crate::unexpected_token!($x);
157        $crate::std_compile_error!($crate::std_concat!(
158            "unexpected token '",
159            $crate::std_stringify!($x),
160            "', expected ident, or lifetime"
161        ));
162    };
163    (
164        [$callback:path]
165        [$($callback_args:tt)*]
166        [$($([$($g:tt)*])+)?]
167        [$($r:tt)*]
168        []
169    ) => {
170        $crate::std_compile_error!($crate::std_concat!(
171            "missing '>' after '",
172            $crate::std_stringify!( < $($($($g)*),+ ,)? ),
173            "'"
174        ));
175    };
176    (
177        @param
178        [$param:tt]
179        [$callback:path]
180        [$($callback_args:tt)*]
181        [$($g:tt)*]
182        [$($r:tt)*]
183        [ : $($token:tt)*]
184    ) => {
185        $crate::parse_generics_impl! {
186            @constrained_param [:]
187            [$param]
188            [] []
189            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
190            [$($token)*]
191        }
192    };
193    (
194        @param
195        [$param:tt]
196        [$callback:path]
197        [$($callback_args:tt)*]
198        [$($g:tt)*]
199        [$($r:tt)*]
200        [ = $($token:tt)*]
201    ) => {
202        $crate::parse_generics_impl! {
203            @constrained_param [=]
204            [$param]
205            [] []
206            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
207            [$($token)*]
208        }
209    };
210    (
211        @param
212        [$param:tt]
213        [$callback:path]
214        [$($callback_args:tt)*]
215        [$($g:tt)*]
216        [$($r:tt)*]
217        [ > $($token:tt)*]
218    ) => {
219        $crate::parse_generics_impl! {
220            @done
221            [$callback] [$($callback_args)*]
222            [$($g)* [$param]]
223            [$($r)* [$param]]
224            []
225            [$($token)*]
226        }
227    };
228    (
229        @param
230        [$param:tt]
231        [$callback:path]
232        [$($callback_args:tt)*]
233        [$($g:tt)*]
234        [$($r:tt)*]
235        [ >> $($token:tt)*]
236    ) => {
237        $crate::parse_generics_impl! {
238            @done
239            [$callback] [$($callback_args)*]
240            [$($g)* [$param]]
241            [$($r)* [$param]]
242            []
243            [ > $($token)*]
244        }
245    };
246    (
247        @param
248        [$param:tt]
249        [$callback:path]
250        [$($callback_args:tt)*]
251        [$($g:tt)*]
252        [$($r:tt)*]
253        [ , > $($token:tt)*]
254    ) => {
255        $crate::parse_generics_impl! {
256            @done
257            [$callback] [$($callback_args)*]
258            [$($g)* [$param]]
259            [$($r)* [$param]]
260            []
261            [$($token)*]
262        }
263    };
264    (
265        @param
266        [$param:tt]
267        [$callback:path]
268        [$($callback_args:tt)*]
269        [$($g:tt)*]
270        [$($r:tt)*]
271        [ , >> $($token:tt)*]
272    ) => {
273        $crate::parse_generics_impl! {
274            @done
275            [$callback] [$($callback_args)*]
276            [$($g)* [$param]]
277            [$($r)* [$param]]
278            []
279            [ > $($token)*]
280        }
281    };
282    (
283        @param
284        [$param:tt]
285        [$callback:path]
286        [$($callback_args:tt)*]
287        [$($g:tt)*]
288        [$($r:tt)*]
289        [ , $($token:tt)*]
290    ) => {
291        $crate::parse_generics_impl! {
292            [$callback] [$($callback_args)*]
293            [$($g)* [$param]]
294            [$($r)* [$param]]
295            [$($token)*]
296        }
297    };
298    (
299        @param
300        [$param:tt]
301        [$callback:path]
302        [$($callback_args:tt)*]
303        [$($g:tt)*]
304        [$($r:tt)*]
305        [$x:tt $($token:tt)*]
306    ) => {
307        $crate::unexpected_token!($x);
308        $crate::std_compile_error!($crate::std_concat!(
309            "unexpected token '",
310            $crate::std_stringify!($x),
311            "', expected ':', '=', ',', or '>'"
312        ));
313    };
314    (
315        @param
316        [$param:tt]
317        [$callback:path]
318        [$($callback_args:tt)*]
319        [$($([$($g:tt)*])+)?]
320        [$($r:tt)*]
321        []
322    ) => {
323        $crate::std_compile_error!($crate::std_concat!(
324            "missing '>' after '",
325            $crate::std_stringify!( < $($($($g)*),+ ,)? $param ),
326            "'"
327        ));
328    };
329    (
330        @constrained_param [$kind:tt]
331        [$param:tt]
332        [$($constraint:tt)*] [$($value:tt)*]
333        [$callback:path]
334        [$($callback_args:tt)*]
335        [$($g:tt)*]
336        [$($r:tt)*]
337        [ < $($token:tt)*]
338    ) => {
339        $crate::parse_generics_impl! {
340            @angles_in_constraint [$kind]
341            [$param]
342            [$($constraint)*] [$($value)*]
343            [] []
344            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
345            [$($token)*]
346        }
347    };
348    (
349        @constrained_param [$kind:tt]
350        [$param:tt]
351        [$($constraint:tt)*] [$($value:tt)*]
352        [$callback:path]
353        [$($callback_args:tt)*]
354        [$($g:tt)*]
355        [$($r:tt)*]
356        [ << $($token:tt)*]
357    ) => {
358        $crate::parse_generics_impl! {
359            @angles_in_constraint [$kind]
360            [$param]
361            [$($constraint)*] [$($value)*]
362            [] []
363            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
364            [ < $($token)*]
365        }
366    };
367    (
368        @constrained_param [$kind:tt]
369        [$param:tt]
370        [$($constraint:tt)*] [$($value:tt)*]
371        [$callback:path]
372        [$($callback_args:tt)*]
373        [$($g:tt)*]
374        [$($r:tt)*]
375        [ > $($token:tt)*]
376    ) => {
377        $crate::parse_generics_impl! {
378            @done
379            [$callback] [$($callback_args)*]
380            [$($g)* [$param : $($constraint)*]]
381            [$($r)* [$param]]
382            []
383            [$($token)*]
384        }
385    };
386    (
387        @constrained_param [$kind:tt]
388        [$param:tt]
389        [$($constraint:tt)*] [$($value:tt)*]
390        [$callback:path]
391        [$($callback_args:tt)*]
392        [$($g:tt)*]
393        [$($r:tt)*]
394        [ >> $($token:tt)*]
395    ) => {
396        $crate::parse_generics_impl! {
397            @done
398            [$callback] [$($callback_args)*]
399            [$($g)* [$param : $($constraint)*]]
400            [$($r)* [$param]]
401            []
402            [ > $($token)*]
403        }
404    };
405    (
406        @constrained_param [$kind:tt]
407        [$param:tt]
408        [$($constraint:tt)*] [$($value:tt)*]
409        [$callback:path]
410        [$($callback_args:tt)*]
411        [$($g:tt)*]
412        [$($r:tt)*]
413        [ , > $($token:tt)*]
414    ) => {
415        $crate::parse_generics_impl! {
416            @done
417            [$callback] [$($callback_args)*]
418            [$($g)* [$param : $($constraint)*]]
419            [$($r)* [$param]]
420            []
421            [$($token)*]
422        }
423    };
424    (
425        @constrained_param [$kind:tt]
426        [$param:tt]
427        [$($constraint:tt)*] [$($value:tt)*]
428        [$callback:path]
429        [$($callback_args:tt)*]
430        [$($g:tt)*]
431        [$($r:tt)*]
432        [ , >> $($token:tt)*]
433    ) => {
434        $crate::parse_generics_impl! {
435            @done
436            [$callback] [$($callback_args)*]
437            [$($g)* [$param : $($constraint)*]]
438            [$($r)* [$param]]
439            []
440            [ > $($token)*]
441        }
442    };
443    (
444        @constrained_param [$kind:tt]
445        [$param:tt]
446        [$($constraint:tt)*] [$($value:tt)*]
447        [$callback:path]
448        [$($callback_args:tt)*]
449        [$($g:tt)*]
450        [$($r:tt)*]
451        [ , $($token:tt)*]
452    ) => {
453        $crate::parse_generics_impl! {
454            [$callback] [$($callback_args)*]
455            [$($g)* [$param : $($constraint)*]]
456            [$($r)* [$param]]
457            [$($token)*]
458        }
459    };
460    (
461        @constrained_param [:]
462        [$param:tt]
463        [$($constraint:tt)*] [$($value:tt)*]
464        [$callback:path]
465        [$($callback_args:tt)*]
466        [$($g:tt)*]
467        [$($r:tt)*]
468        [ = $($token:tt)*]
469    ) => {
470        $crate::parse_generics_impl! {
471            @constrained_param [=]
472            [$param]
473            [$($constraint)*] [$($value)*]
474            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
475            [$($token)*]
476        }
477    };
478    (
479        @constrained_param [:]
480        [$param:tt]
481        [$($constraint:tt)*] [$($value:tt)*]
482        [$callback:path]
483        [$($callback_args:tt)*]
484        [$($g:tt)*]
485        [$($r:tt)*]
486        [ $x:tt $($token:tt)*]
487    ) => {
488        $crate::parse_generics_impl! {
489            @constrained_param [:]
490            [$param]
491            [$($constraint)* $x] [$($value)*]
492            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
493            [$($token)*]
494        }
495    };
496    (
497        @constrained_param [=]
498        [$param:tt]
499        [$($constraint:tt)*] [$($value:tt)*]
500        [$callback:path]
501        [$($callback_args:tt)*]
502        [$($g:tt)*]
503        [$($r:tt)*]
504        [ $x:tt $($token:tt)*]
505    ) => {
506        $crate::parse_generics_impl! {
507            @constrained_param [=]
508            [$param]
509            [$($constraint)*] [$($value)* $x]
510            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
511            [$($token)*]
512        }
513    };
514    (
515        @constrained_param [$kind:tt]
516        [$param:tt]
517        [$($($constraint:tt)+)?] [$($($value:tt)+)?]
518        [$callback:path]
519        [$($callback_args:tt)*]
520        [$($g:tt)*]
521        [$($r:tt)*]
522        []
523    ) => {
524        $crate::std_compile_error!($crate::std_concat!(
525            "missing '>' after '",
526            $crate::std_stringify!( < $($($($g)*),+ ,)? $param $( : $($constraint)+)? $( = $($value)+)? ),
527            "'"
528        ));
529    };
530    (
531        @angles_in_constraint [:]
532        [$param:tt]
533        [$($constraint:tt)*] [$($value:tt)*]
534        [$($inside_angles:tt)*]
535        []
536        [$callback:path]
537        [$($callback_args:tt)*]
538        [$($g:tt)*]
539        [$($r:tt)*]
540        [ > $($token:tt)*]
541    ) => {
542        $crate::parse_generics_impl! {
543            @constrained_param [:]
544            [$param]
545            [$($constraint)* < $($inside_angles)* > ] [$($value)*]
546            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
547            [$($token)*]
548        }
549    };
550    (
551        @angles_in_constraint [=]
552        [$param:tt]
553        [$($constraint:tt)*] [$($value:tt)*]
554        [$($inside_angles:tt)*]
555        []
556        [$callback:path]
557        [$($callback_args:tt)*]
558        [$($g:tt)*]
559        [$($r:tt)*]
560        [ > $($token:tt)*]
561    ) => {
562        $crate::parse_generics_impl! {
563            @constrained_param [=]
564            [$param]
565            [$($constraint)*] [$($value)* < $($inside_angles)* > ]
566            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
567            [$($token)*]
568        }
569    };
570    (
571        @angles_in_constraint [:]
572        [$param:tt]
573        [$($constraint:tt)*] [$($value:tt)*]
574        [$($inside_angles:tt)*]
575        []
576        [$callback:path]
577        [$($callback_args:tt)*]
578        [$($g:tt)*]
579        [$($r:tt)*]
580        [ >> $($token:tt)*]
581    ) => {
582        $crate::parse_generics_impl! {
583            @constrained_param [:]
584            [$param]
585            [$($constraint)* < $($inside_angles)* > ] [$($value)*]
586            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
587            [ > $($token)*]
588        }
589    };
590    (
591        @angles_in_constraint [=]
592        [$param:tt]
593        [$($constraint:tt)*] [$($value:tt)*]
594        [$($inside_angles:tt)*]
595        []
596        [$callback:path]
597        [$($callback_args:tt)*]
598        [$($g:tt)*]
599        [$($r:tt)*]
600        [ >> $($token:tt)*]
601    ) => {
602        $crate::parse_generics_impl! {
603            @constrained_param [=]
604            [$param]
605            [$($constraint)*] [$($value)* < $($inside_angles)* > ]
606            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
607            [ > $($token)*]
608        }
609    };
610    (
611        @angles_in_constraint [$kind:tt]
612        [$param:tt]
613        [$($constraint:tt)*] [$($value:tt)*]
614        [$($inside_angles:tt)*]
615        [[$($parent_level:tt)*] $([$($outer_levels:tt)*])*]
616        [$callback:path]
617        [$($callback_args:tt)*]
618        [$($g:tt)*]
619        [$($r:tt)*]
620        [ > $($token:tt)*]
621    ) => {
622        $crate::parse_generics_impl! {
623            @angles_in_constraint [$kind]
624            [$param]
625            [$($constraint)*] [$($value)*]
626            [$($parent_level)* < $($inside_angles)* > ]
627            [$([$($outer_levels)*])*]
628            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
629            [$($token)*]
630        }
631    };
632    (
633        @angles_in_constraint [$kind:tt]
634        [$param:tt]
635        [$($constraint:tt)*] [$($value:tt)*]
636        [$($inside_angles:tt)*]
637        [[$($parent_level:tt)*] $([$($outer_levels:tt)*])*]
638        [$callback:path]
639        [$($callback_args:tt)*]
640        [$($g:tt)*]
641        [$($r:tt)*]
642        [ >> $($token:tt)*]
643    ) => {
644        $crate::parse_generics_impl! {
645            @angles_in_constraint [$kind]
646            [$param]
647            [$($constraint)*] [$($value)*]
648            [$($parent_level)* < $($inside_angles)* > ]
649            [$([$($outer_levels)*])*]
650            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
651            [ > $($token)*]
652        }
653    };
654    (
655        @angles_in_constraint [$kind:tt]
656        [$param:tt]
657        [$($constraint:tt)*] [$($value:tt)*]
658        [$($inside_angles:tt)*]
659        [$([$($outer_levels:tt)*])*]
660        [$callback:path]
661        [$($callback_args:tt)*]
662        [$($g:tt)*]
663        [$($r:tt)*]
664        [ < $($token:tt)*]
665    ) => {
666        $crate::parse_generics_impl! {
667            @angles_in_constraint [$kind]
668            [$param]
669            [$($constraint)*] [$($value)*]
670            []
671            [[$($inside_angles:tt)*] $([$($outer_levels)*])*]
672            [$callback] [$($callback_args)*] [$($g)*] [$($r)*]
673            [$($token)*]
674        }
675    };
676    (
677        @angles_in_constraint [$kind:tt]
678        [$param:tt]
679        [$($constraint:tt)*] [$($value:tt)*]
680        [$($inside_angles:tt)*]
681        [$([$($outer_levels:tt)*])*]
682        [$callback:path]
683        [$($callback_args:tt)*]
684        [$($g:tt)*]
685        [$($r:tt)*]
686        [ << $($token:tt)*]
687    ) => {
688        $crate::parse_generics_impl! {
689            @angles_in_constraint [$kind]
690            [$param]
691            [$($constraint)*] [$($value)*]
692            []
693            [[$($inside_angles:tt)*] $([$($outer_levels)*])*]
694            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
695            [ < $($token)*]
696        }
697    };
698    (
699        @angles_in_constraint [$kind:tt]
700        [$param:tt]
701        [$($constraint:tt)*] [$($value:tt)*]
702        [$($inside_angles:tt)*]
703        [$([$($outer_levels:tt)*])*]
704        [$callback:path]
705        [$($callback_args:tt)*]
706        [$($g:tt)*]
707        [$($r:tt)*]
708        [$x:tt $($token:tt)*]
709    ) => {
710        $crate::parse_generics_impl! {
711            @angles_in_constraint [$kind]
712            [$param]
713            [$($constraint)*] [$($value)*]
714            [$($inside_angles)* $x]
715            [$([$($outer_levels)*])*]
716            [$callback] [$($callback_args)*] [$($g)*] [$($r)*] 
717            [$($token)*]
718        }
719    };
720    (
721        @angles_in_constraint [:]
722        [$param:tt]
723        [$($constraint:tt)*] [$($($value:tt)+)?]
724        [$($inside_angles:tt)*]
725        [$([$($outer_levels:tt)*])*]
726        [$callback:path]
727        [$($callback_args:tt)*]
728        [$($([$($g:tt)*])+)?]
729        [$($r:tt)*]
730        []
731    ) => {
732        $crate::std_compile_error!($crate::std_concat!(
733            "missing '>' after '",
734            $crate::std_stringify!(
735                < $($($($g)*),+ ,)? $param
736                : $($constraint)* $( < $($outer_levels)* )* < $($inside_angles)*
737                $( = $($value)+)?
738            ),
739            "'"
740        ));
741    };
742    (
743        @angles_in_constraint [=]
744        [$param:tt]
745        [$($($constraint:tt)+)?] [$($value:tt)*]
746        [$($inside_angles:tt)*]
747        [$([$($outer_levels:tt)*])*]
748        [$callback:path]
749        [$($callback_args:tt)*]
750        [$($([$($g:tt)*])+)?]
751        [$($r:tt)*]
752        []
753    ) => {
754        $crate::std_compile_error!($crate::std_concat!(
755            "missing '>' after '",
756            $crate::std_stringify!(
757                < $($($($g)*),+ ,)? $param
758                $( : $($constraint)+)?
759                = $($value)* $( < $($outer_levels)* )* < $($inside_angles)*
760            ),
761            "'"
762        ));
763    };
764    (
765        @done
766        [$callback:path]
767        [$($callback_args:tt)*]
768        [$([$($g:tt)*])+]
769        [$([$($r:tt)*])+]
770        [$($inter:tt)*]
771        [ ; $($token:tt)*]
772    ) => {
773        $callback ! {
774            $($callback_args)*
775            [ < $($($g)*),+ > ]
776            [ < $($($r)*),+ > ]
777            []
778            $($inter)* ; $($token)*
779        }
780    };
781    (
782        @done
783        [$callback:path]
784        [$($callback_args:tt)*]
785        [$([$($g:tt)*])+]
786        [$([$($r:tt)*])+]
787        [$($inter:tt)*]
788        [ $( { $($body:tt)* } $($token:tt)* )? ]
789    ) => {
790        $callback ! {
791            $($callback_args)*
792            [ < $($($g)*),+ > ]
793            [ < $($($r)*),+ > ]
794            []
795            $($inter)* $( { $($body)* } $($token)* )?
796        }
797    };
798    (
799        @done
800        [$callback:path]
801        [$($callback_args:tt)*]
802        [$([$($g:tt)*])+]
803        [$([$($r:tt)*])+]
804        [$($inter:tt)*]
805        [where $($token:tt)*]
806    ) => {
807        $crate::parse_where_clause_impl! {
808            [$callback]
809            [$($callback_args)*]
810            [ < $($($g)*),+ > ]
811            [ < $($($r)*),+ > ]
812            [] [$($inter)*] [$($token)*]
813        }
814    };
815    (
816        @done
817        [$callback:path]
818        [$($callback_args:tt)*]
819        [$($g:tt)+]
820        [$($r:tt)+]
821        [$($inter:tt)*]
822        [$token:tt $($other_tokens:tt)*]
823    ) => {
824        $crate::parse_generics_impl! {
825            @done
826            [$callback] [$($callback_args)*]
827            [$($g)+]
828            [$($r)+]
829            [$($inter)* $token]
830            [$($other_tokens)*]
831        }
832    };
833}
834
835#[doc(hidden)]
836#[macro_export]
837macro_rules! parse_where_clause_impl {
838    (
839        [$callback:path]
840        [$($callback_args:tt)*]
841        [$($g:tt)*] [$($r:tt)*]
842        [$($($w:tt)+)?]
843        [$($inter:tt)*] 
844        [ ; $($token:tt)* ]
845    ) => {
846        $callback ! { 
847            $($callback_args)*
848            [$($g)*]
849            [$($r)*]
850            [$(where $($w)+)?]
851            $($inter)* ; $($token)*
852        }
853    };
854    (
855        [$callback:path]
856        [$($callback_args:tt)*]
857        [$($g:tt)*] [$($r:tt)*]
858        [$($($w:tt)+)?]
859        [$($inter:tt)*] 
860        [ $( { $($body:tt)* } $($token:tt)* )? ]
861    ) => {
862        $callback ! { 
863            $($callback_args)*
864            [$($g)*]
865            [$($r)*]
866            [$(where $($w)+)?]
867            $($inter)* $( { $($body)* } $($token)* )?
868        }
869    };
870    (
871        [$callback:path]
872        [$($callback_args:tt)*]
873        [$($g:tt)*] [$($r:tt)*]
874        [$($w:tt)*]
875        [$($inter:tt)*] 
876        [$token:tt $($other_tokens:tt)*]
877    ) => {
878        $crate::parse_where_clause_impl! { 
879            [$callback]
880            [$($callback_args)*]
881            [$($g)*] [$($r)*]
882            [$($w)* $token]
883            [$($inter)*]
884            [$($other_tokens)*]
885        }
886    };
887}
888
889#[doc(hidden)]
890#[macro_export]
891macro_rules! deny_where_clause_impl {
892    (
893        [$callback:path]
894        [$($callback_args:tt)*]
895        [$($inter:tt)*]
896        [ ; $($token:tt)*]
897    ) => {
898        $callback ! {
899            $($callback_args)*
900            []
901            []
902            []
903            $($inter)* ; $($token)*
904        }
905    };
906    (
907        [$callback:path]
908        [$($callback_args:tt)*]
909        [$($inter:tt)*]
910        [ $( { $($body:tt)* } $($token:tt)* )? ]
911    ) => {
912        $callback ! {
913            $($callback_args)*
914            []
915            []
916            []
917            $($inter)* $( { $($body)* } $($token)* )?
918        }
919    };
920    (
921        [$callback:path]
922        [$($callback_args:tt)*]
923        [$($inter:tt)*]
924        [where $($token:tt)*]
925    ) => {
926        $crate::std_compile_error!("unexpected 'where' without generics preceding");
927    };
928    (
929        [$callback:path]
930        [$($callback_args:tt)*]
931        [$($inter:tt)*]
932        [$token:tt $($other_tokens:tt)*]
933    ) => {
934        $crate::deny_where_clause_impl! {
935            [$callback] [$($callback_args)*]
936            [$($inter)* $token]
937            [$($other_tokens)*]
938        }
939    };
940}
941
942/// Concats several [`parse`](parse) calls results together.
943///
944/// This macro accepts an input in the following form:
945///
946/// ```ignore
947/// $callback:path { $($callback_args:tt)* }
948/// $($(
949///     [$(<$($g:tt)*>)?] [$(<$($r:tt)*>)?] [$(where $($w:tt)*)?]
950/// ),+ $(,)?)?
951/// ```
952///
953/// and expands into
954///
955/// ```ignore
956/// $callback! {
957///     $($callback_args)*
958///     [$(<$($g)+>)?] [$(<$($r)+>)?] [$(where $($w)+)?]
959/// }
960/// ```
961#[macro_export]
962macro_rules! concat {
963    (
964        $callback:path { $($callback_args:tt)* }
965        $($(
966            [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
967        ),+ $(,)?)?
968    ) => {
969        $crate::concat_impl! {
970            [$callback] [$($callback_args)*]
971            [$($([$($g)*])+)?] [$($([$($r)*])+)?] [$($([$($w)*])+)?]
972        }
973    };
974}
975
976#[doc(hidden)]
977#[macro_export]
978macro_rules! concat_impl {
979    (
980        [$callback:path] [$($callback_args:tt)*]
981        [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
982    ) => {
983        $crate::concat_g_impl! {
984            @list
985            [$crate::concat_impl] [@g [$callback] [$($callback_args)*] [$($r)*] [$($w)*]]
986            [$($g)*]
987            [] []
988        }
989    };
990    (
991        @g
992        [$callback:path] [$($callback_args:tt)*] [$($r:tt)*] [$($w:tt)*]
993        [$($g:tt)*]
994    ) => {
995        $crate::concat_r_impl! {
996            @list
997            [$crate::concat_impl] [@r [$callback] [$($callback_args)*] [$($g)*] [$($w)*]]
998            [$($r)*]
999            [] []
1000        }
1001    };
1002    (
1003        @r
1004        [$callback:path] [$($callback_args:tt)*] [$($g:tt)*] [$($w:tt)*]
1005        [$($r:tt)*]
1006    ) => {
1007        $crate::concat_w_impl! {
1008            @list
1009            [$crate::concat_impl] [@w [$callback] [$($callback_args)*] [$($g)*] [$($r)*]]
1010            [$($w)*]
1011            []
1012        }
1013    };
1014    (
1015        @w
1016        [$callback:path] [$($callback_args:tt)*] [$($g:tt)*] [$($r:tt)*]
1017        [$($w:tt)*]
1018    ) => {
1019        $callback ! {
1020            $($callback_args)*
1021            [$($g)*] [$($r)*] [$($w)*]
1022        }
1023    };
1024}
1025
1026#[doc(hidden)]
1027#[macro_export]
1028macro_rules! concat_g_impl {
1029    (
1030        @list
1031        [$callback:path] [$($callback_args:tt)*]
1032        [[] $($list:tt)*]
1033        [$($lifetimes:tt)*] [$($types:tt)*]
1034    ) => {
1035        $crate::concat_g_impl! {
1036            @list
1037            [$callback] [$($callback_args)*]
1038            [$($list)*]
1039            [$($lifetimes)*] [$($types)*]
1040        }
1041    };
1042    (
1043        @list
1044        [$callback:path] [$($callback_args:tt)*]
1045        [[ < $($item:tt)* ] $($list:tt)*]
1046        [$($lifetimes:tt)*] [$($types:tt)*]
1047    ) => {
1048        $crate::concat_g_impl! {
1049            @item
1050            [$callback] [$($callback_args)*] [$($list)*]
1051            [$($lifetimes)*] [$($types)*]
1052            []
1053            [$($item)*]
1054        }
1055    };
1056    (
1057        @list
1058        [$callback:path] [$($callback_args:tt)*]
1059        [[$token:tt $($item:tt)*] $($list:tt)*]
1060        [$($lifetimes:tt)*] [$($types:tt)*]
1061    ) => {
1062        $crate::unexpected_token!($token);
1063        $crate::std_compile_error!($crate::std_concat!(
1064            "invalid generics '",
1065            $crate::std_stringify!($token $($item)*),
1066            "'"
1067        ));
1068    };
1069    (
1070        @list
1071        [$callback:path] [$($callback_args:tt)*]
1072        []
1073        [] []
1074    ) => {
1075        $callback ! {
1076            $($callback_args)*
1077            []
1078        }
1079    };
1080    (
1081        @list
1082        [$callback:path] [$($callback_args:tt)*]
1083        []
1084        [$([$($lifetime:tt)*])+] []
1085    ) => {
1086        $callback ! {
1087            $($callback_args)*
1088            [ < $($($lifetime)*),+ > ]
1089        }
1090    };
1091    (
1092        @list
1093        [$callback:path] [$($callback_args:tt)*]
1094        []
1095        [] [$([$($ty:tt)*])+]
1096    ) => {
1097        $callback ! {
1098            $($callback_args)*
1099            [ < $($($ty)*),+ > ]
1100        }
1101    };
1102    (
1103        @list
1104        [$callback:path] [$($callback_args:tt)*]
1105        []
1106        [$([$($lifetime:tt)*])+] [$([$($ty:tt)*])+]
1107    ) => {
1108        $callback ! {
1109            $($callback_args)*
1110            [ < $($($lifetime)*),+ , $($($ty)*),+ > ]
1111        }
1112    };
1113    (
1114        @item
1115        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1116        [$($lifetimes:tt)*] [$($types:tt)*]
1117        [$lifetime:lifetime $($constraint:tt)*]
1118        [, $($tail:tt)*]
1119    ) => {
1120        $crate::concat_g_impl! {
1121            @item
1122            [$callback] [$($callback_args)*] [$($list)*]
1123            [$($lifetimes)* [$lifetime $($constraint)*]] [$($types)*]
1124            []
1125            [$($tail)*]
1126        }
1127    };
1128    (
1129        @item
1130        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1131        [$($lifetimes:tt)*] [$($types:tt)*]
1132        [$ty:ident $($constraint:tt)*]
1133        [, $($tail:tt)*]
1134    ) => {
1135        $crate::concat_g_impl! {
1136            @item
1137            [$callback] [$($callback_args)*] [$($list)*]
1138            [$($lifetimes)*] [$($types)* [$ty $($constraint)*]]
1139            []
1140            [$($tail)*]
1141        }
1142    };
1143    (
1144        @item
1145        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1146        [$($lifetimes:tt)*] [$($types:tt)*]
1147        [$($param:tt)*]
1148        [ < $($tail:tt)*]
1149    ) => {
1150        $crate::concat_g_impl! {
1151            @angles
1152            [$callback] [$($callback_args)*] [$($list)*]
1153            [$($lifetimes)*] [$($types)*] [$($param)*]
1154            []
1155            []
1156            [$($tail)*]
1157        }
1158    };
1159    (
1160        @item
1161        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1162        [$($lifetimes:tt)*] [$($types:tt)*]
1163        [$lifetime:lifetime $($constraint:tt)*]
1164        [ > ]
1165    ) => {
1166        $crate::concat_g_impl! {
1167            @list
1168            [$callback] [$($callback_args)*]
1169            [$($list)*]
1170            [$($lifetimes)* [$lifetime $($constraint)*]] [$($types)*]
1171        }
1172    };
1173    (
1174        @item
1175        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1176        [$($lifetimes:tt)*] [$($types:tt)*]
1177        [$ty:ident $($constraint:tt)*]
1178        [ > ]
1179    ) => {
1180        $crate::concat_g_impl! {
1181            @list
1182            [$callback] [$($callback_args)*]
1183            [$($list)*]
1184            [$($lifetimes)*] [$($types)* [$ty $($constraint)*]]
1185        }
1186    };
1187    (
1188        @item
1189        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1190        [$($lifetimes:tt)*] [$($types:tt)*]
1191        []
1192        [ > ]
1193    ) => {
1194        $crate::concat_g_impl! {
1195            @list
1196            [$callback] [$($callback_args)*]
1197            [$($list)*]
1198            [$($lifetimes)*] [$($types)*]
1199        }
1200    };
1201    (
1202        @item
1203        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1204        [$($lifetimes:tt)*] [$($types:tt)*]
1205        [$($param:tt)*]
1206        [ > $token:tt $($tail:tt)* ]
1207    ) => {
1208        $crate::unexpected_token($token);
1209        $crate::std_compile_error!($crate::std_concat!(
1210            "unexpected tail '",
1211            $crate::std_stringify!($token $($tail)*),
1212            "' after generics"
1213        ));
1214    };
1215    (
1216        @item
1217        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1218        [$($lifetimes:tt)*] [$($types:tt)*]
1219        [$($param:tt)*]
1220        [$token:tt $($tail:tt)*]
1221    ) => {
1222        $crate::concat_g_impl! {
1223            @item
1224            [$callback] [$($callback_args)*] [$($list)*]
1225            [$($lifetimes)*] [$($types)*]
1226            [$($param)* $token]
1227            [$($tail)*]
1228        }
1229    };
1230    (
1231        @item
1232        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1233        [$($lifetimes:tt)*] [$($types:tt)*]
1234        [$($param:tt)*]
1235        []
1236    ) => {
1237        $crate::std_compile_error!("unclosed generics");
1238    };
1239    (
1240        @angles
1241        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1242        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1243        [$($outer_levels:tt)*]
1244        [$($content:tt)*]
1245        [ < $($tail:tt)*]
1246    ) => {
1247        $crate::concat_g_impl! {
1248            @angles
1249            [$callback] [$($callback_args)*] [$($list)*]
1250            [$($lifetimes)*] [$($types)*] [$($param)*]
1251            [[$($content)*] $($outer_levels)*]
1252            []
1253            [$($tail)*]
1254        }
1255    };
1256    (
1257        @angles
1258        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1259        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1260        [[$($outer_level:tt)*] $($other_outer_levels:tt)*]
1261        [$($content:tt)*]
1262        [ > $($tail:tt)*]
1263    ) => {
1264        $crate::concat_g_impl! {
1265            @angles
1266            [$callback] [$($callback_args)*] [$($list)*]
1267            [$($lifetimes)*] [$($types)*] [$($param)*]
1268            [$($other_outer_levels)*]
1269            [$($outer_level)* < $($content)* > ]
1270            [$($tail)*]
1271        }
1272    };
1273    (
1274        @angles
1275        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1276        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1277        []
1278        [$($content:tt)*]
1279        [ > $($tail:tt)*]
1280    ) => {
1281        $crate::concat_g_impl! {
1282            @item
1283            [$callback] [$($callback_args)*] [$($list)*]
1284            [$($lifetimes)*] [$($types)*]
1285            [$($param)* < $($content)* > ]
1286            [$($tail)*]
1287        }
1288    };
1289    (
1290        @angles
1291        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1292        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1293        [$($outer_levels:tt)*]
1294        [$($content:tt)*]
1295        [ $token:tt $($tail:tt)*]
1296    ) => {
1297        $crate::concat_g_impl! {
1298            @angles
1299            [$callback] [$($callback_args)*] [$($list)*]
1300            [$($lifetimes)*] [$($types)*] [$($param)*]
1301            [$($outer_levels)*]
1302            [$($content)* $token]
1303            [$($tail)*]
1304        }
1305    };
1306    (
1307        @angles
1308        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1309        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1310        [$($outer_levels:tt)*]
1311        [$($content:tt)+]
1312        []
1313    ) => {
1314        $crate::std_compile_error!($crate::std_concat!(
1315            "unclosed angles: '<",
1316            $crate::std_stringify!($($content)+),
1317            "'"
1318        ));
1319    };
1320    (
1321        @angles
1322        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1323        [$($lifetimes:tt)*] [$($types:tt)*] [$($param:tt)*]
1324        [$($outer_levels:tt)*]
1325        []
1326        []
1327    ) => {
1328        $crate::std_compile_error!("unclosed angles");
1329    };
1330}
1331
1332#[doc(hidden)]
1333#[macro_export]
1334macro_rules! concat_r_impl {
1335    (
1336        @list
1337        [$callback:path] [$($callback_args:tt)*]
1338        [[] $($list:tt)*]
1339        [$($lifetimes:tt)*] [$($types:tt)*]
1340    ) => {
1341        $crate::concat_r_impl! {
1342            @list
1343            [$callback] [$($callback_args)*]
1344            [$($list)*]
1345            [$($lifetimes)*] [$($types)*]
1346        }
1347    };
1348    (
1349        @list
1350        [$callback:path] [$($callback_args:tt)*]
1351        [[ < $($item:tt)* ] $($list:tt)*]
1352        [$($lifetimes:tt)*] [$($types:tt)*]
1353    ) => {
1354        $crate::concat_r_impl! {
1355            @item
1356            [$callback] [$($callback_args)*] [$($list)*]
1357            [$($lifetimes)*] [$($types)*]
1358            [, $($item)*]
1359        }
1360    };
1361    (
1362        @list
1363        [$callback:path] [$($callback_args:tt)*]
1364        [[$token:tt $($item:tt)*] $($list:tt)*]
1365        [$($lifetimes:tt)*] [$($types:tt)*]
1366    ) => {
1367        $crate::unexpected_token!($token);
1368        $crate::std_compile_error!($crate::std_concat!(
1369            "invalid generics without constraints '",
1370            $crate::std_stringify!($token $($item)*),
1371            "'"
1372        ));
1373    };
1374    (
1375        @list
1376        [$callback:path] [$($callback_args:tt)*]
1377        []
1378        [] []
1379    ) => {
1380        $callback ! {
1381            $($callback_args)*
1382            []
1383        }
1384    };
1385    (
1386        @list
1387        [$callback:path] [$($callback_args:tt)*]
1388        []
1389        [$([$($lifetime:tt)*])+] []
1390    ) => {
1391        $callback ! {
1392            $($callback_args)*
1393            [ < $($($lifetime)*),+ > ]
1394        }
1395    };
1396    (
1397        @list
1398        [$callback:path] [$($callback_args:tt)*]
1399        []
1400        [] [$([$($ty:tt)*])+]
1401    ) => {
1402        $callback ! {
1403            $($callback_args)*
1404            [ < $($($ty)*),+ > ]
1405        }
1406    };
1407    (
1408        @list
1409        [$callback:path] [$($callback_args:tt)*]
1410        []
1411        [$([$($lifetime:tt)*])+] [$([$($ty:tt)*])+]
1412    ) => {
1413        $callback ! {
1414            $($callback_args)*
1415            [ < $($($lifetime)*),+ , $($($ty)*),+ > ]
1416        }
1417    };
1418    (
1419        @item
1420        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1421        [$($lifetimes:tt)*] [$($types:tt)*]
1422        [, $lifetime:lifetime $($tail:tt)*]
1423    ) => {
1424        $crate::concat_r_impl! {
1425            @item
1426            [$callback] [$($callback_args)*] [$($list)*]
1427            [$($lifetimes)* [$lifetime]] [$($types)*]
1428            [$($tail)*]
1429        }
1430    };
1431    (
1432        @item
1433        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1434        [$($lifetimes:tt)*] [$($types:tt)*]
1435        [, $ty:ident $($tail:tt)*]
1436    ) => {
1437        $crate::concat_r_impl! {
1438            @item
1439            [$callback] [$($callback_args)*] [$($list)*]
1440            [$($lifetimes)*] [$($types)* [$ty]]
1441            [$($tail)*]
1442        }
1443    };
1444    (
1445        @item
1446        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1447        [$($lifetimes:tt)*] [$($types:tt)*]
1448        [ $(,)? > ]
1449    ) => {
1450        $crate::concat_r_impl! {
1451            @list
1452            [$callback] [$($callback_args)*]
1453            [$($list)*]
1454            [$($lifetimes)*] [$($types)*]
1455        }
1456    };
1457    (
1458        @item
1459        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1460        [$($lifetimes:tt)*] [$($types:tt)*]
1461        [$token:tt $($tail:tt)*]
1462    ) => {
1463        $crate::unexpected_token!($token);
1464        $crate::std_compile_error!($crate::std_concat!(
1465            "invalid generics without constraints '",
1466            $crate::std_stringify!($token $($tail)*),
1467            "'"
1468        ));
1469    };
1470    (
1471        @item
1472        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1473        [$($lifetimes:tt)*] [$($types:tt)*]
1474        []
1475    ) => {
1476        $crate::std_compile_error!("unclosed generics without constraints");
1477    };
1478}
1479
1480#[doc(hidden)]
1481#[macro_export]
1482macro_rules! concat_w_impl {
1483    (
1484        @list
1485        [$callback:path] [$($callback_args:tt)*]
1486        [[] $($list:tt)*]
1487        [$($w:tt)*]
1488    ) => {
1489        $crate::concat_w_impl! {
1490            @list
1491            [$callback] [$($callback_args)*]
1492            [$($list)*]
1493            [$($w)*]
1494        }
1495    };
1496    (
1497        @list
1498        [$callback:path] [$($callback_args:tt)*]
1499        [[ where ] $($list:tt)*]
1500        [$($w:tt)*]
1501    ) => {
1502        $crate::concat_w_impl! {
1503            @list
1504            [$callback] [$($callback_args)*]
1505            [$($list)*]
1506            [$($w)*]
1507        }
1508    };
1509    (
1510        @list
1511        [$callback:path] [$($callback_args:tt)*]
1512        [[ where $($item:tt)* ] $($list:tt)*]
1513        [$($w:tt)*]
1514    ) => {
1515        $crate::concat_w_impl! {
1516            @item
1517            [$callback] [$($callback_args)*] [$($list)*]
1518            [$($w)*]
1519            []
1520            [$($item)*]
1521        }
1522    };
1523    (
1524        @list
1525        [$callback:path] [$($callback_args:tt)*]
1526        [[$token:tt $($item:tt)*] $($list:tt)*]
1527        [$($w:tt)*]
1528    ) => {
1529        $crate::unexpected_token!($token);
1530        $crate::std_compile_error!($crate::std_concat!(
1531            "invalid where clause '",
1532            $crate::std_stringify!($token $($item)*),
1533            "'"
1534        ));
1535    };
1536    (
1537        @list
1538        [$callback:path] [$($callback_args:tt)*]
1539        []
1540        [$($([$($w:tt)*])+)?]
1541    ) => {
1542        $callback ! {
1543            $($callback_args)*
1544            [$(where $($($w)*),+)?]
1545        }
1546    };
1547    (
1548        @item
1549        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1550        [$($w:tt)*]
1551        [$($item:tt)*]
1552        [$(,)?]
1553    ) => {
1554        $crate::concat_w_impl! {
1555            @list
1556            [$callback] [$($callback_args)*]
1557            [$($list)*]
1558            [$($w)* [$($item)*]]
1559        }
1560    };
1561    (
1562        @item
1563        [$callback:path] [$($callback_args:tt)*] [$($list:tt)*]
1564        [$($w:tt)*]
1565        [$($item:tt)*]
1566        [$token:tt $($tail:tt)*]
1567    ) => {
1568        $crate::concat_w_impl! {
1569            @item
1570            [$callback] [$($callback_args)*] [$($list)*]
1571            [$($w)*]
1572            [$($item)* $token]
1573            [$($tail)*]
1574        }
1575    };
1576}
1577
1578#[cfg(test)]
1579mod tests {
1580    macro_rules! impl_test_trait {
1581        (
1582            struct $name:ident $($token:tt)*
1583        ) => {
1584            parse! {
1585                impl_test_trait {
1586                    @impl struct $name
1587                }
1588                $($token)*
1589            }
1590        };
1591        (
1592            @impl struct $name:ident [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1593        ) => {
1594            impl $($g)* TestTrait for $name $($r)* $($w)* { }
1595        };
1596    }
1597
1598    trait TestTrait { }
1599
1600    struct TestStruct { }
1601
1602    impl_test_trait! {
1603        struct TestStruct { }
1604    }
1605
1606    struct TestGenericStruct<'a, T: 'static> {
1607        a: &'a (),
1608        t: T,
1609    }
1610
1611    impl_test_trait! {
1612        struct TestGenericStruct<'a, T: 'static> { }
1613    }
1614
1615    struct TestGenericStructWithDefaultParameter<T=()>(T);
1616
1617    impl_test_trait! {
1618        struct TestGenericStructWithDefaultParameter<T=()>(T);
1619    }
1620
1621    struct TestGenericStructWithConstrainedDefaultParameter<T: 'static = ()>(T);
1622
1623    impl_test_trait! {
1624        struct TestGenericStructWithConstrainedDefaultParameter<T: 'static = ()>(T);
1625    }
1626
1627    #[test]
1628    fn it_works() {
1629        let test_struct = TestStruct { };
1630        let _: &dyn TestTrait = &test_struct;
1631        let test_generic_struct = TestGenericStruct {
1632            a: &(),
1633            t: ()
1634        };
1635        let _ = test_generic_struct.a;
1636        let _ = test_generic_struct.t;
1637        let _: &dyn TestTrait = &test_generic_struct;
1638        let test_generic_struct_ = TestGenericStructWithDefaultParameter(());
1639        let _: &dyn TestTrait = &test_generic_struct_;
1640        let _ = test_generic_struct_.0;
1641        let test_generic_struct__ = TestGenericStructWithConstrainedDefaultParameter(());
1642        let _: &dyn TestTrait = &test_generic_struct__;
1643        let _ = test_generic_struct__.0;
1644    }
1645
1646    macro_rules! impl_tr {
1647        (
1648            struct $name:ident $($token:tt)*
1649        ) => {
1650            parse! {
1651                impl_tr {
1652                    @impl struct $name
1653                }
1654                $($token)*
1655            }
1656        };
1657        (
1658            @impl struct $name:ident [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] become $tr:ident $($body:tt)*
1659        ) => {
1660            impl $($g)* $tr for $name $($r)* $($w)* { }
1661        };
1662    }
1663
1664    #[allow(dead_code)]
1665    trait TestTrait2 { }
1666
1667    impl_tr! {
1668        struct TestStruct become TestTrait2 { }
1669    }
1670
1671    impl_tr! {
1672        struct TestGenericStruct<'a, T> become TestTrait2 where T: 'static { }
1673    }
1674
1675    macro_rules! struct_A {
1676        (
1677        ) => {
1678            concat_g_impl! {
1679                @list
1680                [struct_A] [@struct]
1681                [[ < 'a, 'b > ] [] [ < 'c, 'd, T: 'static, > ]]
1682                [] []
1683            }
1684        };
1685        (
1686            @struct [$($g:tt)*]
1687        ) => {
1688            struct A $($g)* {
1689                a: &'a (),
1690                b: &'b (),
1691                c: &'c (),
1692                d: &'d T,
1693            }
1694        };
1695    }
1696
1697    struct_A!();
1698
1699    #[test]
1700    fn run_concat_g_impl() {
1701        let x = A { a: &(), b: &(), c: &(), d: &0u16 };
1702        let _ = x.a;
1703        let _ = x.b;
1704        let _ = x.c;
1705        let _ = x.d;
1706    }
1707
1708    macro_rules! struct_B {
1709        (
1710        ) => {
1711            concat_r_impl! {
1712                @list
1713                [struct_B] [@struct]
1714                [[ < 'a, 'b > ] [] [ < 'c, 'd, T, > ]]
1715                [] []
1716            }
1717        };
1718        (
1719            @struct [$($g:tt)*]
1720        ) => {
1721            struct B $($g)* {
1722                a: &'a (),
1723                b: &'b (),
1724                c: &'c (),
1725                d: &'d T,
1726            }
1727        };
1728    }
1729
1730    struct_B!();
1731
1732    #[test]
1733    fn run_concat_r_impl() {
1734        let x = B { a: &(), b: &(), c: &(), d: &0u16 };
1735        let _ = x.a;
1736        let _ = x.b;
1737        let _ = x.c;
1738        let _ = x.d;
1739    }
1740
1741    macro_rules! descr {
1742        (
1743            impl $($token:tt)*
1744        ) => {
1745            parse! {
1746                descr {
1747                    @impl
1748                }
1749                $($token)*
1750            }
1751        };
1752        (
1753            @impl [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $t:ty { $($body:tt)* }
1754        ) => {
1755            impl $($g)* $t $($w)* { $($body)* }
1756        };
1757    }
1758
1759    struct Test<A>(A);
1760
1761    descr! {
1762        impl<A> Test<A> where A: Clone {
1763            fn a(&self) { }
1764        }
1765    }
1766
1767    #[test]
1768    fn run_test() {
1769        let x: Test<u32> = Test(7);
1770        x.a();
1771    }
1772}