generics2/
lib.rs

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