1 //! Tests specific to declarative macros, aka macros by example. This covers
2 //! both stable `macro_rules!` macros as well as unstable `macro` macros.
3
4 mod tt_conversion;
5 mod matching;
6 mod meta_syntax;
7 mod metavar_expr;
8 mod regression;
9
10 use expect_test::expect;
11
12 use crate::macro_expansion_tests::check;
13
14 #[test]
token_mapping_smoke_test()15 fn token_mapping_smoke_test() {
16 check(
17 r#"
18 // +tokenids
19 macro_rules! f {
20 ( struct $ident:ident ) => {
21 struct $ident {
22 map: ::std::collections::HashSet<()>,
23 }
24 };
25 }
26
27 // +tokenids
28 f!(struct MyTraitMap2);
29 "#,
30 expect![[r##"
31 // call ids will be shifted by Shift(30)
32 // +tokenids
33 macro_rules! f {#0
34 (#1 struct#2 $#3ident#4:#5ident#6 )#1 =#7>#8 {#9
35 struct#10 $#11ident#12 {#13
36 map#14:#15 :#16:#17std#18:#19:#20collections#21:#22:#23HashSet#24<#25(#26)#26>#27,#28
37 }#13
38 }#9;#29
39 }#0
40
41 // // +tokenids
42 // f!(struct#1 MyTraitMap2#2);
43 struct#10 MyTraitMap2#32 {#13
44 map#14:#15 ::std#18::collections#21::HashSet#24<#25(#26)#26>#27,#28
45 }#13
46 "##]],
47 );
48 }
49
50 #[test]
token_mapping_floats()51 fn token_mapping_floats() {
52 // Regression test for https://github.com/rust-lang/rust-analyzer/issues/12216
53 // (and related issues)
54 check(
55 r#"
56 // +tokenids
57 macro_rules! f {
58 ($($tt:tt)*) => {
59 $($tt)*
60 };
61 }
62
63 // +tokenids
64 f! {
65 fn main() {
66 1;
67 1.0;
68 let x = 1;
69 }
70 }
71
72
73 "#,
74 expect![[r##"
75 // call ids will be shifted by Shift(18)
76 // +tokenids
77 macro_rules! f {#0
78 (#1$#2(#3$#4tt#5:#6tt#7)#3*#8)#1 =#9>#10 {#11
79 $#12(#13$#14tt#15)#13*#16
80 }#11;#17
81 }#0
82
83 // // +tokenids
84 // f! {
85 // fn#1 main#2() {
86 // 1#5;#6
87 // 1.0#7;#8
88 // let#9 x#10 =#11 1#12;#13
89 // }
90 // }
91 fn#19 main#20(#21)#21 {#22
92 1#23;#24
93 1.0#25;#26
94 let#27 x#28 =#29 1#30;#31
95 }#22
96
97
98 "##]],
99 );
100 }
101 #[test]
float_field_access_macro_input()102 fn float_field_access_macro_input() {
103 check(
104 r#"
105 macro_rules! foo {
106 ($expr:expr) => {
107 fn foo() {
108 $expr;
109 }
110 };
111 }
112 foo!(x .0.1);
113 foo!(x .2. 3);
114 foo!(x .4 .5);
115 "#,
116 expect![[r#"
117 macro_rules! foo {
118 ($expr:expr) => {
119 fn foo() {
120 $expr;
121 }
122 };
123 }
124 fn foo() {
125 (x.0.1);
126 }
127 fn foo() {
128 (x.2.3);
129 }
130 fn foo() {
131 (x.4.5);
132 }
133 "#]],
134 );
135 }
136
137 #[test]
mbe_smoke_test()138 fn mbe_smoke_test() {
139 check(
140 r#"
141 macro_rules! impl_froms {
142 ($e:ident: $($v:ident),*) => {
143 $(
144 impl From<$v> for $e {
145 fn from(it: $v) -> $e { $e::$v(it) }
146 }
147 )*
148 }
149 }
150 impl_froms!(TokenTree: Leaf, Subtree);
151 "#,
152 expect![[r#"
153 macro_rules! impl_froms {
154 ($e:ident: $($v:ident),*) => {
155 $(
156 impl From<$v> for $e {
157 fn from(it: $v) -> $e { $e::$v(it) }
158 }
159 )*
160 }
161 }
162 impl From<Leaf> for TokenTree {
163 fn from(it: Leaf) -> TokenTree {
164 TokenTree::Leaf(it)
165 }
166 }
167 impl From<Subtree> for TokenTree {
168 fn from(it: Subtree) -> TokenTree {
169 TokenTree::Subtree(it)
170 }
171 }
172 "#]],
173 );
174 }
175
176 #[test]
wrong_nesting_level()177 fn wrong_nesting_level() {
178 check(
179 r#"
180 macro_rules! m {
181 ($($i:ident);*) => ($i)
182 }
183 m!{a}
184 "#,
185 expect![[r#"
186 macro_rules! m {
187 ($($i:ident);*) => ($i)
188 }
189 /* error: expected simple binding, found nested binding `i` */
190 "#]],
191 );
192 }
193
194 #[test]
match_by_first_token_literally()195 fn match_by_first_token_literally() {
196 check(
197 r#"
198 macro_rules! m {
199 ($i:ident) => ( mod $i {} );
200 (= $i:ident) => ( fn $i() {} );
201 (+ $i:ident) => ( struct $i; )
202 }
203 m! { foo }
204 m! { = bar }
205 m! { + Baz }
206 "#,
207 expect![[r#"
208 macro_rules! m {
209 ($i:ident) => ( mod $i {} );
210 (= $i:ident) => ( fn $i() {} );
211 (+ $i:ident) => ( struct $i; )
212 }
213 mod foo {}
214 fn bar() {}
215 struct Baz;
216 "#]],
217 );
218 }
219
220 #[test]
match_by_last_token_literally()221 fn match_by_last_token_literally() {
222 check(
223 r#"
224 macro_rules! m {
225 ($i:ident) => ( mod $i {} );
226 ($i:ident =) => ( fn $i() {} );
227 ($i:ident +) => ( struct $i; )
228 }
229 m! { foo }
230 m! { bar = }
231 m! { Baz + }
232 "#,
233 expect![[r#"
234 macro_rules! m {
235 ($i:ident) => ( mod $i {} );
236 ($i:ident =) => ( fn $i() {} );
237 ($i:ident +) => ( struct $i; )
238 }
239 mod foo {}
240 fn bar() {}
241 struct Baz;
242 "#]],
243 );
244 }
245
246 #[test]
match_by_ident()247 fn match_by_ident() {
248 check(
249 r#"
250 macro_rules! m {
251 ($i:ident) => ( mod $i {} );
252 (spam $i:ident) => ( fn $i() {} );
253 (eggs $i:ident) => ( struct $i; )
254 }
255 m! { foo }
256 m! { spam bar }
257 m! { eggs Baz }
258 "#,
259 expect![[r#"
260 macro_rules! m {
261 ($i:ident) => ( mod $i {} );
262 (spam $i:ident) => ( fn $i() {} );
263 (eggs $i:ident) => ( struct $i; )
264 }
265 mod foo {}
266 fn bar() {}
267 struct Baz;
268 "#]],
269 );
270 }
271
272 #[test]
match_by_separator_token()273 fn match_by_separator_token() {
274 check(
275 r#"
276 macro_rules! m {
277 ($($i:ident),*) => ($(mod $i {} )*);
278 ($($i:ident)#*) => ($(fn $i() {} )*);
279 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
280 }
281
282 m! { foo, bar }
283
284 m! { foo# bar }
285
286 m! { Foo,# Bar }
287 "#,
288 expect![[r##"
289 macro_rules! m {
290 ($($i:ident),*) => ($(mod $i {} )*);
291 ($($i:ident)#*) => ($(fn $i() {} )*);
292 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
293 }
294
295 mod foo {}
296 mod bar {}
297
298 fn foo() {}
299 fn bar() {}
300
301 struct Foo;
302 struct Bar;
303 "##]],
304 );
305 }
306
307 #[test]
test_match_group_pattern_with_multiple_defs()308 fn test_match_group_pattern_with_multiple_defs() {
309 check(
310 r#"
311 macro_rules! m {
312 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
313 }
314 m! { foo, bar }
315 "#,
316 expect![[r#"
317 macro_rules! m {
318 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
319 }
320 impl Bar {
321 fn foo() {}
322 fn bar() {}
323 }
324 "#]],
325 );
326 }
327
328 #[test]
test_match_group_pattern_with_multiple_statement()329 fn test_match_group_pattern_with_multiple_statement() {
330 check(
331 r#"
332 macro_rules! m {
333 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
334 }
335 m! { foo, bar }
336 "#,
337 expect![[r#"
338 macro_rules! m {
339 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
340 }
341 fn baz() {
342 foo();
343 bar();
344 }
345 "#]],
346 )
347 }
348
349 #[test]
test_match_group_pattern_with_multiple_statement_without_semi()350 fn test_match_group_pattern_with_multiple_statement_without_semi() {
351 check(
352 r#"
353 macro_rules! m {
354 ($($i:ident),*) => ( fn baz() { $($i() );* } );
355 }
356 m! { foo, bar }
357 "#,
358 expect![[r#"
359 macro_rules! m {
360 ($($i:ident),*) => ( fn baz() { $($i() );* } );
361 }
362 fn baz() {
363 foo();
364 bar()
365 }
366 "#]],
367 )
368 }
369
370 #[test]
test_match_group_empty_fixed_token()371 fn test_match_group_empty_fixed_token() {
372 check(
373 r#"
374 macro_rules! m {
375 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
376 }
377 m!{#abc}
378 "#,
379 expect![[r##"
380 macro_rules! m {
381 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
382 }
383 fn baz() {}
384 "##]],
385 )
386 }
387
388 #[test]
test_match_group_in_subtree()389 fn test_match_group_in_subtree() {
390 check(
391 r#"
392 macro_rules! m {
393 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
394 }
395 m! { fn baz { a b } }
396 "#,
397 expect![[r#"
398 macro_rules! m {
399 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
400 }
401 fn baz() {
402 a();
403 b();
404 }
405 "#]],
406 )
407 }
408
409 #[test]
test_expr_order()410 fn test_expr_order() {
411 check(
412 r#"
413 macro_rules! m {
414 ($ i:expr) => { fn bar() { $ i * 3; } }
415 }
416 // +tree
417 m! { 1 + 2 }
418 "#,
419 expect![[r#"
420 macro_rules! m {
421 ($ i:expr) => { fn bar() { $ i * 3; } }
422 }
423 fn bar() {
424 (1+2)*3;
425 }
426 // MACRO_ITEMS@0..17
427 // FN@0..17
428 // FN_KW@0..2 "fn"
429 // NAME@2..5
430 // IDENT@2..5 "bar"
431 // PARAM_LIST@5..7
432 // L_PAREN@5..6 "("
433 // R_PAREN@6..7 ")"
434 // BLOCK_EXPR@7..17
435 // STMT_LIST@7..17
436 // L_CURLY@7..8 "{"
437 // EXPR_STMT@8..16
438 // BIN_EXPR@8..15
439 // PAREN_EXPR@8..13
440 // L_PAREN@8..9 "("
441 // BIN_EXPR@9..12
442 // LITERAL@9..10
443 // INT_NUMBER@9..10 "1"
444 // PLUS@10..11 "+"
445 // LITERAL@11..12
446 // INT_NUMBER@11..12 "2"
447 // R_PAREN@12..13 ")"
448 // STAR@13..14 "*"
449 // LITERAL@14..15
450 // INT_NUMBER@14..15 "3"
451 // SEMICOLON@15..16 ";"
452 // R_CURLY@16..17 "}"
453
454 "#]],
455 )
456 }
457
458 #[test]
test_match_group_with_multichar_sep()459 fn test_match_group_with_multichar_sep() {
460 check(
461 r#"
462 macro_rules! m {
463 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
464 }
465 m! (fn baz { true false } );
466 "#,
467 expect![[r#"
468 macro_rules! m {
469 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
470 }
471 fn baz() -> bool {
472 true && false
473 }
474 "#]],
475 );
476
477 check(
478 r#"
479 macro_rules! m {
480 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
481 }
482 m! (fn baz { true && false } );
483 "#,
484 expect![[r#"
485 macro_rules! m {
486 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
487 }
488 fn baz() -> bool {
489 true && false
490 }
491 "#]],
492 );
493 }
494
495 #[test]
test_match_group_zero_match()496 fn test_match_group_zero_match() {
497 check(
498 r#"
499 macro_rules! m { ( $($i:ident)* ) => (); }
500 m!();
501 "#,
502 expect![[r#"
503 macro_rules! m { ( $($i:ident)* ) => (); }
504
505 "#]],
506 );
507 }
508
509 #[test]
test_match_group_in_group()510 fn test_match_group_in_group() {
511 check(
512 r#"
513 macro_rules! m {
514 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
515 }
516 m! ( (a b) );
517 "#,
518 expect![[r#"
519 macro_rules! m {
520 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
521 }
522 ok![(a b)];
523 "#]],
524 )
525 }
526
527 #[test]
test_expand_to_item_list()528 fn test_expand_to_item_list() {
529 check(
530 r#"
531 macro_rules! structs {
532 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
533 }
534
535 // +tree
536 structs!(Foo, Bar);
537 "#,
538 expect![[r#"
539 macro_rules! structs {
540 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
541 }
542
543 struct Foo {
544 field: u32
545 }
546 struct Bar {
547 field: u32
548 }
549 // MACRO_ITEMS@0..40
550 // STRUCT@0..20
551 // STRUCT_KW@0..6 "struct"
552 // NAME@6..9
553 // IDENT@6..9 "Foo"
554 // RECORD_FIELD_LIST@9..20
555 // L_CURLY@9..10 "{"
556 // RECORD_FIELD@10..19
557 // NAME@10..15
558 // IDENT@10..15 "field"
559 // COLON@15..16 ":"
560 // PATH_TYPE@16..19
561 // PATH@16..19
562 // PATH_SEGMENT@16..19
563 // NAME_REF@16..19
564 // IDENT@16..19 "u32"
565 // R_CURLY@19..20 "}"
566 // STRUCT@20..40
567 // STRUCT_KW@20..26 "struct"
568 // NAME@26..29
569 // IDENT@26..29 "Bar"
570 // RECORD_FIELD_LIST@29..40
571 // L_CURLY@29..30 "{"
572 // RECORD_FIELD@30..39
573 // NAME@30..35
574 // IDENT@30..35 "field"
575 // COLON@35..36 ":"
576 // PATH_TYPE@36..39
577 // PATH@36..39
578 // PATH_SEGMENT@36..39
579 // NAME_REF@36..39
580 // IDENT@36..39 "u32"
581 // R_CURLY@39..40 "}"
582
583 "#]],
584 );
585 }
586
587 #[test]
test_two_idents()588 fn test_two_idents() {
589 check(
590 r#"
591 macro_rules! m {
592 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
593 }
594 m! { foo, bar }
595 "#,
596 expect![[r#"
597 macro_rules! m {
598 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
599 }
600 fn foo() {
601 let a = foo;
602 let b = bar;
603 }
604 "#]],
605 );
606 }
607
608 #[test]
test_tt_to_stmts()609 fn test_tt_to_stmts() {
610 check(
611 r#"
612 macro_rules! m {
613 () => {
614 let a = 0;
615 a = 10 + 1;
616 a
617 }
618 }
619
620 fn f() -> i32 {
621 m!/*+tree*/{}
622 }
623 "#,
624 expect![[r#"
625 macro_rules! m {
626 () => {
627 let a = 0;
628 a = 10 + 1;
629 a
630 }
631 }
632
633 fn f() -> i32 {
634 let a = 0;
635 a = 10+1;
636 a
637 // MACRO_STMTS@0..15
638 // LET_STMT@0..7
639 // LET_KW@0..3 "let"
640 // IDENT_PAT@3..4
641 // NAME@3..4
642 // IDENT@3..4 "a"
643 // EQ@4..5 "="
644 // LITERAL@5..6
645 // INT_NUMBER@5..6 "0"
646 // SEMICOLON@6..7 ";"
647 // EXPR_STMT@7..14
648 // BIN_EXPR@7..13
649 // PATH_EXPR@7..8
650 // PATH@7..8
651 // PATH_SEGMENT@7..8
652 // NAME_REF@7..8
653 // IDENT@7..8 "a"
654 // EQ@8..9 "="
655 // BIN_EXPR@9..13
656 // LITERAL@9..11
657 // INT_NUMBER@9..11 "10"
658 // PLUS@11..12 "+"
659 // LITERAL@12..13
660 // INT_NUMBER@12..13 "1"
661 // SEMICOLON@13..14 ";"
662 // PATH_EXPR@14..15
663 // PATH@14..15
664 // PATH_SEGMENT@14..15
665 // NAME_REF@14..15
666 // IDENT@14..15 "a"
667
668 }
669 "#]],
670 );
671 }
672
673 #[test]
test_match_literal()674 fn test_match_literal() {
675 check(
676 r#"
677 macro_rules! m {
678 ('(') => { fn l_paren() {} }
679 }
680 m!['('];
681 "#,
682 expect![[r#"
683 macro_rules! m {
684 ('(') => { fn l_paren() {} }
685 }
686 fn l_paren() {}
687 "#]],
688 );
689 }
690
691 #[test]
test_parse_macro_def_simple()692 fn test_parse_macro_def_simple() {
693 cov_mark::check!(parse_macro_def_simple);
694 check(
695 r#"
696 macro m($id:ident) { fn $id() {} }
697 m!(bar);
698 "#,
699 expect![[r#"
700 macro m($id:ident) { fn $id() {} }
701 fn bar() {}
702 "#]],
703 );
704 }
705
706 #[test]
test_parse_macro_def_rules()707 fn test_parse_macro_def_rules() {
708 cov_mark::check!(parse_macro_def_rules);
709
710 check(
711 r#"
712 macro m {
713 ($id:ident) => { fn $id() {} }
714 }
715 m!(bar);
716 "#,
717 expect![[r#"
718 macro m {
719 ($id:ident) => { fn $id() {} }
720 }
721 fn bar() {}
722 "#]],
723 );
724 }
725
726 #[test]
test_macro_2_0_panic_2015()727 fn test_macro_2_0_panic_2015() {
728 check(
729 r#"
730 macro panic_2015 {
731 () => (),
732 (bar) => (),
733 }
734 panic_2015!(bar);
735 "#,
736 expect![[r#"
737 macro panic_2015 {
738 () => (),
739 (bar) => (),
740 }
741
742 "#]],
743 );
744 }
745
746 #[test]
test_path()747 fn test_path() {
748 check(
749 r#"
750 macro_rules! m {
751 ($p:path) => { fn foo() { let a = $p; } }
752 }
753
754 m! { foo }
755
756 m! { bar::<u8>::baz::<u8> }
757 "#,
758 expect![[r#"
759 macro_rules! m {
760 ($p:path) => { fn foo() { let a = $p; } }
761 }
762
763 fn foo() {
764 let a = foo;
765 }
766
767 fn foo() {
768 let a = bar::<u8>::baz::<u8> ;
769 }
770 "#]],
771 );
772 }
773
774 #[test]
test_two_paths()775 fn test_two_paths() {
776 check(
777 r#"
778 macro_rules! m {
779 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
780 }
781 m! { foo, bar }
782 "#,
783 expect![[r#"
784 macro_rules! m {
785 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
786 }
787 fn foo() {
788 let a = foo;
789 let b = bar;
790 }
791 "#]],
792 );
793 }
794
795 #[test]
test_path_with_path()796 fn test_path_with_path() {
797 check(
798 r#"
799 macro_rules! m {
800 ($p:path) => { fn foo() { let a = $p::bar; } }
801 }
802 m! { foo }
803 "#,
804 expect![[r#"
805 macro_rules! m {
806 ($p:path) => { fn foo() { let a = $p::bar; } }
807 }
808 fn foo() {
809 let a = foo::bar;
810 }
811 "#]],
812 );
813 }
814
815 #[test]
test_expr()816 fn test_expr() {
817 check(
818 r#"
819 macro_rules! m {
820 ($e:expr) => { fn bar() { $e; } }
821 }
822
823 m! { 2 + 2 * baz(3).quux() }
824 "#,
825 expect![[r#"
826 macro_rules! m {
827 ($e:expr) => { fn bar() { $e; } }
828 }
829
830 fn bar() {
831 (2+2*baz(3).quux());
832 }
833 "#]],
834 )
835 }
836
837 #[test]
test_last_expr()838 fn test_last_expr() {
839 check(
840 r#"
841 macro_rules! vec {
842 ($($item:expr),*) => {{
843 let mut v = Vec::new();
844 $( v.push($item); )*
845 v
846 }};
847 }
848
849 fn f() {
850 vec![1,2,3];
851 }
852 "#,
853 expect![[r#"
854 macro_rules! vec {
855 ($($item:expr),*) => {{
856 let mut v = Vec::new();
857 $( v.push($item); )*
858 v
859 }};
860 }
861
862 fn f() {
863 {
864 let mut v = Vec::new();
865 v.push(1);
866 v.push(2);
867 v.push(3);
868 v
869 };
870 }
871 "#]],
872 );
873 }
874
875 #[test]
test_expr_with_attr()876 fn test_expr_with_attr() {
877 check(
878 r#"
879 macro_rules! m { ($a:expr) => { ok!(); } }
880 m!(#[allow(a)]());
881 "#,
882 expect![[r#"
883 macro_rules! m { ($a:expr) => { ok!(); } }
884 ok!();
885 "#]],
886 )
887 }
888
889 #[test]
test_ty()890 fn test_ty() {
891 check(
892 r#"
893 macro_rules! m {
894 ($t:ty) => ( fn bar() -> $t {} )
895 }
896 m! { Baz<u8> }
897 "#,
898 expect![[r#"
899 macro_rules! m {
900 ($t:ty) => ( fn bar() -> $t {} )
901 }
902 fn bar() -> Baz<u8> {}
903 "#]],
904 )
905 }
906
907 #[test]
test_ty_with_complex_type()908 fn test_ty_with_complex_type() {
909 check(
910 r#"
911 macro_rules! m {
912 ($t:ty) => ( fn bar() -> $ t {} )
913 }
914
915 m! { &'a Baz<u8> }
916
917 m! { extern "Rust" fn() -> Ret }
918 "#,
919 expect![[r#"
920 macro_rules! m {
921 ($t:ty) => ( fn bar() -> $ t {} )
922 }
923
924 fn bar() -> &'a Baz<u8> {}
925
926 fn bar() -> extern "Rust" fn() -> Ret {}
927 "#]],
928 );
929 }
930
931 #[test]
test_pat_()932 fn test_pat_() {
933 check(
934 r#"
935 macro_rules! m {
936 ($p:pat) => { fn foo() { let $p; } }
937 }
938 m! { (a, b) }
939 "#,
940 expect![[r#"
941 macro_rules! m {
942 ($p:pat) => { fn foo() { let $p; } }
943 }
944 fn foo() {
945 let (a, b);
946 }
947 "#]],
948 );
949 }
950
951 #[test]
test_stmt()952 fn test_stmt() {
953 check(
954 r#"
955 macro_rules! m {
956 ($s:stmt) => ( fn bar() { $s; } )
957 }
958 m! { 2 }
959 m! { let a = 0 }
960 "#,
961 expect![[r#"
962 macro_rules! m {
963 ($s:stmt) => ( fn bar() { $s; } )
964 }
965 fn bar() {
966 2;
967 }
968 fn bar() {
969 let a = 0;
970 }
971 "#]],
972 )
973 }
974
975 #[test]
test_single_item()976 fn test_single_item() {
977 check(
978 r#"
979 macro_rules! m { ($i:item) => ( $i ) }
980 m! { mod c {} }
981 "#,
982 expect![[r#"
983 macro_rules! m { ($i:item) => ( $i ) }
984 mod c {}
985 "#]],
986 )
987 }
988
989 #[test]
test_all_items()990 fn test_all_items() {
991 check(
992 r#"
993 macro_rules! m { ($($i:item)*) => ($($i )*) }
994 m! {
995 extern crate a;
996 mod b;
997 mod c {}
998 use d;
999 const E: i32 = 0;
1000 static F: i32 = 0;
1001 impl G {}
1002 struct H;
1003 enum I { Foo }
1004 trait J {}
1005 fn h() {}
1006 extern {}
1007 type T = u8;
1008 }
1009 "#,
1010 expect![[r#"
1011 macro_rules! m { ($($i:item)*) => ($($i )*) }
1012 extern crate a;
1013 mod b;
1014 mod c {}
1015 use d;
1016 const E: i32 = 0;
1017 static F: i32 = 0;
1018 impl G {}
1019 struct H;
1020 enum I {
1021 Foo
1022 }
1023 trait J {}
1024 fn h() {}
1025 extern {}
1026 type T = u8;
1027 "#]],
1028 );
1029 }
1030
1031 #[test]
test_block()1032 fn test_block() {
1033 check(
1034 r#"
1035 macro_rules! m { ($b:block) => { fn foo() $b } }
1036 m! { { 1; } }
1037 "#,
1038 expect![[r#"
1039 macro_rules! m { ($b:block) => { fn foo() $b } }
1040 fn foo() {
1041 1;
1042 }
1043 "#]],
1044 );
1045 }
1046
1047 #[test]
test_meta()1048 fn test_meta() {
1049 check(
1050 r#"
1051 macro_rules! m {
1052 ($m:meta) => ( #[$m] fn bar() {} )
1053 }
1054 m! { cfg(target_os = "windows") }
1055 m! { hello::world }
1056 "#,
1057 expect![[r##"
1058 macro_rules! m {
1059 ($m:meta) => ( #[$m] fn bar() {} )
1060 }
1061 #[cfg(target_os = "windows")] fn bar() {}
1062 #[hello::world] fn bar() {}
1063 "##]],
1064 );
1065 }
1066
1067 #[test]
test_meta_doc_comments()1068 fn test_meta_doc_comments() {
1069 cov_mark::check!(test_meta_doc_comments);
1070 check(
1071 r#"
1072 macro_rules! m {
1073 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1074 }
1075 m! {
1076 /// Single Line Doc 1
1077 /**
1078 MultiLines Doc
1079 */
1080 }
1081 "#,
1082 expect![[r##"
1083 macro_rules! m {
1084 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1085 }
1086 #[doc = " Single Line Doc 1"]
1087 #[doc = "\n MultiLines Doc\n "] fn bar() {}
1088 "##]],
1089 );
1090 }
1091
1092 #[test]
test_meta_extended_key_value_attributes()1093 fn test_meta_extended_key_value_attributes() {
1094 check(
1095 r#"
1096 macro_rules! m {
1097 (#[$m:meta]) => ( #[$m] fn bar() {} )
1098 }
1099 m! { #[doc = concat!("The `", "bla", "` lang item.")] }
1100 "#,
1101 expect![[r##"
1102 macro_rules! m {
1103 (#[$m:meta]) => ( #[$m] fn bar() {} )
1104 }
1105 #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {}
1106 "##]],
1107 );
1108 }
1109
1110 #[test]
test_meta_doc_comments_non_latin()1111 fn test_meta_doc_comments_non_latin() {
1112 check(
1113 r#"
1114 macro_rules! m {
1115 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1116 }
1117 m! {
1118 /// 錦瑟無端五十弦,一弦一柱思華年。
1119 /**
1120 莊生曉夢迷蝴蝶,望帝春心託杜鵑。
1121 */
1122 }
1123 "#,
1124 expect![[r##"
1125 macro_rules! m {
1126 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1127 }
1128 #[doc = " 錦瑟無端五十弦,一弦一柱思華年。"]
1129 #[doc = "\n 莊生曉夢迷蝴蝶,望帝春心託杜鵑。\n "] fn bar() {}
1130 "##]],
1131 );
1132 }
1133
1134 #[test]
test_meta_doc_comments_escaped_characters()1135 fn test_meta_doc_comments_escaped_characters() {
1136 check(
1137 r#"
1138 macro_rules! m {
1139 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1140 }
1141 m! {
1142 /// \ " '
1143 }
1144 "#,
1145 expect![[r##"
1146 macro_rules! m {
1147 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1148 }
1149 #[doc = " \\ \" \'"] fn bar() {}
1150 "##]],
1151 );
1152 }
1153
1154 #[test]
test_tt_block()1155 fn test_tt_block() {
1156 check(
1157 r#"
1158 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1159 m! { { 1; } }
1160 "#,
1161 expect![[r#"
1162 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1163 fn foo() {
1164 1;
1165 }
1166 "#]],
1167 );
1168 }
1169
1170 #[test]
test_tt_group()1171 fn test_tt_group() {
1172 check(
1173 r#"
1174 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1175 m! { fn foo() {} }"
1176 "#,
1177 expect![[r#"
1178 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1179 fn foo() {}"
1180 "#]],
1181 );
1182 }
1183
1184 #[test]
test_tt_composite()1185 fn test_tt_composite() {
1186 check(
1187 r#"
1188 macro_rules! m { ($tt:tt) => { ok!(); } }
1189 m! { => }
1190 m! { = > }
1191 "#,
1192 expect![[r#"
1193 macro_rules! m { ($tt:tt) => { ok!(); } }
1194 ok!();
1195 /* error: leftover tokens */ok!();
1196 "#]],
1197 );
1198 }
1199
1200 #[test]
test_tt_composite2()1201 fn test_tt_composite2() {
1202 check(
1203 r#"
1204 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1205 m! {#}
1206 "#,
1207 expect![[r##"
1208 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1209 abs!( = > #);
1210 "##]],
1211 );
1212 }
1213
1214 #[test]
test_tt_with_composite_without_space()1215 fn test_tt_with_composite_without_space() {
1216 // Test macro input without any spaces
1217 // See https://github.com/rust-lang/rust-analyzer/issues/6692
1218 check(
1219 r#"
1220 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1221 m!(==,Foo::Bool)
1222 "#,
1223 expect![[r#"
1224 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1225 ok!();
1226 "#]],
1227 );
1228 }
1229
1230 #[test]
test_underscore()1231 fn test_underscore() {
1232 check(
1233 r#"
1234 macro_rules! m { ($_:tt) => { ok!(); } }
1235 m! { => }
1236 "#,
1237 expect![[r#"
1238 macro_rules! m { ($_:tt) => { ok!(); } }
1239 ok!();
1240 "#]],
1241 );
1242 }
1243
1244 #[test]
test_underscore_not_greedily()1245 fn test_underscore_not_greedily() {
1246 check(
1247 r#"
1248 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1249 macro_rules! m1 {
1250 ($($a:ident)* _) => { ok!(); }
1251 }
1252 m1![a b c d _];
1253
1254 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1255 macro_rules! m2 {
1256 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1257 }
1258 m2![a => b c => d _ => ou]
1259 "#,
1260 expect![[r#"
1261 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1262 macro_rules! m1 {
1263 ($($a:ident)* _) => { ok!(); }
1264 }
1265 ok!();
1266
1267 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1268 macro_rules! m2 {
1269 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1270 }
1271 ok!();
1272 "#]],
1273 );
1274 }
1275
1276 #[test]
test_underscore_flavors()1277 fn test_underscore_flavors() {
1278 check(
1279 r#"
1280 macro_rules! m1 { ($a:ty) => { ok!(); } }
1281 m1![_];
1282
1283 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1284 m2!['_];
1285 "#,
1286 expect![[r#"
1287 macro_rules! m1 { ($a:ty) => { ok!(); } }
1288 ok!();
1289
1290 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1291 ok!();
1292 "#]],
1293 );
1294 }
1295
1296 #[test]
test_vertical_bar_with_pat_param()1297 fn test_vertical_bar_with_pat_param() {
1298 check(
1299 r#"
1300 macro_rules! m { (|$pat:pat_param| ) => { ok!(); } }
1301 m! { |x| }
1302 "#,
1303 expect![[r#"
1304 macro_rules! m { (|$pat:pat_param| ) => { ok!(); } }
1305 ok!();
1306 "#]],
1307 );
1308 }
1309
1310 #[test]
test_new_std_matches()1311 fn test_new_std_matches() {
1312 check(
1313 r#"
1314 macro_rules! matches {
1315 ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => {
1316 match $expression {
1317 $pattern $(if $guard)? => true,
1318 _ => false
1319 }
1320 };
1321 }
1322 fn main() {
1323 matches!(0, 0 | 1 if true);
1324 }
1325 "#,
1326 expect![[r#"
1327 macro_rules! matches {
1328 ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => {
1329 match $expression {
1330 $pattern $(if $guard)? => true,
1331 _ => false
1332 }
1333 };
1334 }
1335 fn main() {
1336 match 0 {
1337 0|1 if true =>true , _=>false
1338 };
1339 }
1340 "#]],
1341 );
1342 }
1343
1344 #[test]
test_dollar_crate_lhs_is_not_meta()1345 fn test_dollar_crate_lhs_is_not_meta() {
1346 check(
1347 r#"
1348 macro_rules! m {
1349 ($crate) => { err!(); };
1350 () => { ok!(); };
1351 }
1352 m!{}
1353 "#,
1354 expect![[r#"
1355 macro_rules! m {
1356 ($crate) => { err!(); };
1357 () => { ok!(); };
1358 }
1359 ok!();
1360 "#]],
1361 );
1362 }
1363
1364 #[test]
test_lifetime()1365 fn test_lifetime() {
1366 check(
1367 r#"
1368 macro_rules! m {
1369 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1370 }
1371 m! {'a}
1372 "#,
1373 expect![[r#"
1374 macro_rules! m {
1375 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1376 }
1377 struct Ref<'a> {
1378 s: &'a str
1379 }
1380 "#]],
1381 );
1382 }
1383
1384 #[test]
test_literal()1385 fn test_literal() {
1386 check(
1387 r#"
1388 macro_rules! m {
1389 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1390 }
1391 m!(u8, 0);
1392 "#,
1393 expect![[r#"
1394 macro_rules! m {
1395 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1396 }
1397 const VALUE: u8 = 0;
1398 "#]],
1399 );
1400
1401 check(
1402 r#"
1403 macro_rules! m {
1404 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1405 }
1406 m!(i32, -1);
1407 "#,
1408 expect![[r#"
1409 macro_rules! m {
1410 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1411 }
1412 const VALUE: i32 = -1;
1413 "#]],
1414 );
1415 }
1416
1417 #[test]
test_boolean_is_ident()1418 fn test_boolean_is_ident() {
1419 check(
1420 r#"
1421 macro_rules! m {
1422 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1423 }
1424 m!(true, false);
1425 "#,
1426 expect![[r#"
1427 macro_rules! m {
1428 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1429 }
1430 const VALUE: (bool, bool) = (true , false );
1431 "#]],
1432 );
1433 }
1434
1435 #[test]
test_vis()1436 fn test_vis() {
1437 check(
1438 r#"
1439 macro_rules! m {
1440 ($vis:vis $name:ident) => { $vis fn $name() {} }
1441 }
1442 m!(pub foo);
1443 m!(foo);
1444 "#,
1445 expect![[r#"
1446 macro_rules! m {
1447 ($vis:vis $name:ident) => { $vis fn $name() {} }
1448 }
1449 pub fn foo() {}
1450 fn foo() {}
1451 "#]],
1452 );
1453 }
1454
1455 #[test]
test_inner_macro_rules()1456 fn test_inner_macro_rules() {
1457 check(
1458 r#"
1459 macro_rules! m {
1460 ($a:ident, $b:ident, $c:tt) => {
1461 macro_rules! inner {
1462 ($bi:ident) => { fn $bi() -> u8 { $c } }
1463 }
1464
1465 inner!($a);
1466 fn $b() -> u8 { $c }
1467 }
1468 }
1469 m!(x, y, 1);
1470 "#,
1471 expect![[r#"
1472 macro_rules! m {
1473 ($a:ident, $b:ident, $c:tt) => {
1474 macro_rules! inner {
1475 ($bi:ident) => { fn $bi() -> u8 { $c } }
1476 }
1477
1478 inner!($a);
1479 fn $b() -> u8 { $c }
1480 }
1481 }
1482 macro_rules !inner {
1483 ($bi: ident) = > {
1484 fn $bi()-> u8 {
1485 1
1486 }
1487 }
1488 }
1489 inner!(x);
1490 fn y() -> u8 {
1491 1
1492 }
1493 "#]],
1494 );
1495 }
1496
1497 #[test]
test_expr_after_path_colons()1498 fn test_expr_after_path_colons() {
1499 check(
1500 r#"
1501 macro_rules! m {
1502 ($k:expr) => { fn f() { K::$k; } }
1503 }
1504 // +tree +errors
1505 m!(C("0"));
1506 "#,
1507 expect![[r#"
1508 macro_rules! m {
1509 ($k:expr) => { fn f() { K::$k; } }
1510 }
1511 /* parse error: expected identifier */
1512 /* parse error: expected SEMICOLON */
1513 /* parse error: expected SEMICOLON */
1514 /* parse error: expected expression, item or let statement */
1515 fn f() {
1516 K::(C("0"));
1517 }
1518 // MACRO_ITEMS@0..19
1519 // FN@0..19
1520 // FN_KW@0..2 "fn"
1521 // NAME@2..3
1522 // IDENT@2..3 "f"
1523 // PARAM_LIST@3..5
1524 // L_PAREN@3..4 "("
1525 // R_PAREN@4..5 ")"
1526 // BLOCK_EXPR@5..19
1527 // STMT_LIST@5..19
1528 // L_CURLY@5..6 "{"
1529 // EXPR_STMT@6..10
1530 // PATH_EXPR@6..10
1531 // PATH@6..10
1532 // PATH@6..7
1533 // PATH_SEGMENT@6..7
1534 // NAME_REF@6..7
1535 // IDENT@6..7 "K"
1536 // COLON2@7..9 "::"
1537 // ERROR@9..10
1538 // L_PAREN@9..10 "("
1539 // EXPR_STMT@10..16
1540 // CALL_EXPR@10..16
1541 // PATH_EXPR@10..11
1542 // PATH@10..11
1543 // PATH_SEGMENT@10..11
1544 // NAME_REF@10..11
1545 // IDENT@10..11 "C"
1546 // ARG_LIST@11..16
1547 // L_PAREN@11..12 "("
1548 // LITERAL@12..15
1549 // STRING@12..15 "\"0\""
1550 // R_PAREN@15..16 ")"
1551 // ERROR@16..17
1552 // R_PAREN@16..17 ")"
1553 // SEMICOLON@17..18 ";"
1554 // R_CURLY@18..19 "}"
1555
1556 "#]],
1557 );
1558 }
1559
1560 #[test]
test_match_is_not_greedy()1561 fn test_match_is_not_greedy() {
1562 check(
1563 r#"
1564 macro_rules! foo {
1565 ($($i:ident $(,)*),*) => {};
1566 }
1567 foo!(a,b);
1568 "#,
1569 expect![[r#"
1570 macro_rules! foo {
1571 ($($i:ident $(,)*),*) => {};
1572 }
1573
1574 "#]],
1575 );
1576 }
1577
1578 #[test]
expr_interpolation()1579 fn expr_interpolation() {
1580 check(
1581 r#"
1582 macro_rules! m { ($expr:expr) => { map($expr) } }
1583 fn f() {
1584 let _ = m!(x + foo);
1585 }
1586 "#,
1587 expect![[r#"
1588 macro_rules! m { ($expr:expr) => { map($expr) } }
1589 fn f() {
1590 let _ = map((x+foo));
1591 }
1592 "#]],
1593 )
1594 }
1595
1596 #[test]
mbe_are_not_attributes()1597 fn mbe_are_not_attributes() {
1598 check(
1599 r#"
1600 macro_rules! error {
1601 () => {struct Bar}
1602 }
1603
1604 #[error]
1605 struct Foo;
1606 "#,
1607 expect![[r##"
1608 macro_rules! error {
1609 () => {struct Bar}
1610 }
1611
1612 #[error]
1613 struct Foo;
1614 "##]],
1615 )
1616 }
1617
1618 #[test]
test_punct_without_space()1619 fn test_punct_without_space() {
1620 // Puncts are "glued" greedily.
1621 check(
1622 r#"
1623 macro_rules! foo {
1624 (: : :) => { "1 1 1" };
1625 (: ::) => { "1 2" };
1626 (:: :) => { "2 1" };
1627
1628 (: : : :) => { "1 1 1 1" };
1629 (:: : :) => { "2 1 1" };
1630 (: :: :) => { "1 2 1" };
1631 (: : ::) => { "1 1 2" };
1632 (:: ::) => { "2 2" };
1633 }
1634
1635 fn test() {
1636 foo!(:::);
1637 foo!(: :::);
1638 foo!(::::);
1639 }
1640 "#,
1641 expect![[r#"
1642 macro_rules! foo {
1643 (: : :) => { "1 1 1" };
1644 (: ::) => { "1 2" };
1645 (:: :) => { "2 1" };
1646
1647 (: : : :) => { "1 1 1 1" };
1648 (:: : :) => { "2 1 1" };
1649 (: :: :) => { "1 2 1" };
1650 (: : ::) => { "1 1 2" };
1651 (:: ::) => { "2 2" };
1652 }
1653
1654 fn test() {
1655 "2 1";
1656 "1 2 1";
1657 "2 2";
1658 }
1659 "#]],
1660 );
1661 }
1662