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#[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#[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}