1 //! Tests specific to declarative macros, aka macros by example. This covers
2 //! both stable `macro_rules!` macros as well as unstable `macro` macros.
8 use expect_test::expect;
10 use crate::macro_expansion_tests::check;
16 macro_rules! impl_froms {
17 ($e:ident: $($v:ident),*) => {
19 impl From<$v> for $e {
20 fn from(it: $v) -> $e { $e::$v(it) }
25 impl_froms!(TokenTree: Leaf, Subtree);
28 macro_rules! impl_froms {
29 ($e:ident: $($v:ident),*) => {
31 impl From<$v> for $e {
32 fn from(it: $v) -> $e { $e::$v(it) }
37 impl From<Leaf> for TokenTree {
38 fn from(it:Leaf) -> TokenTree {
42 impl From<Subtree> for TokenTree {
43 fn from(it:Subtree) -> TokenTree {
44 TokenTree::Subtree(it)
52 fn expansion_does_not_parse_as_expression() {
59 fn f() { let _ = stmts!(); }
66 fn f() { let _ = /* error: could not convert tokens */; }
72 fn wrong_nesting_level() {
76 ($($i:ident);*) => ($i)
82 ($($i:ident);*) => ($i)
84 /* error: expected simple binding, found nested binding `i` */
90 fn match_by_first_token_literally() {
94 ($i:ident) => ( mod $i {} );
95 (= $i:ident) => ( fn $i() {} );
96 (+ $i:ident) => ( struct $i; )
104 ($i:ident) => ( mod $i {} );
105 (= $i:ident) => ( fn $i() {} );
106 (+ $i:ident) => ( struct $i; )
116 fn match_by_last_token_literally() {
120 ($i:ident) => ( mod $i {} );
121 ($i:ident =) => ( fn $i() {} );
122 ($i:ident +) => ( struct $i; )
130 ($i:ident) => ( mod $i {} );
131 ($i:ident =) => ( fn $i() {} );
132 ($i:ident +) => ( struct $i; )
142 fn match_by_ident() {
146 ($i:ident) => ( mod $i {} );
147 (spam $i:ident) => ( fn $i() {} );
148 (eggs $i:ident) => ( struct $i; )
156 ($i:ident) => ( mod $i {} );
157 (spam $i:ident) => ( fn $i() {} );
158 (eggs $i:ident) => ( struct $i; )
168 fn match_by_separator_token() {
172 ($($i:ident),*) => ($(mod $i {} )*);
173 ($($i:ident)#*) => ($(fn $i() {} )*);
174 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
185 ($($i:ident),*) => ($(mod $i {} )*);
186 ($($i:ident)#*) => ($(fn $i() {} )*);
187 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
203 fn test_match_group_pattern_with_multiple_defs() {
207 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
213 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
224 fn test_match_group_pattern_with_multiple_statement() {
228 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
234 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
245 fn test_match_group_pattern_with_multiple_statement_without_semi() {
249 ($($i:ident),*) => ( fn baz() { $($i() );* } );
255 ($($i:ident),*) => ( fn baz() { $($i() );* } );
266 fn test_match_group_empty_fixed_token() {
270 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
276 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
284 fn test_match_group_in_subtree() {
288 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
290 m! { fn baz { a b } }
294 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
305 fn test_expr_order() {
309 ($ i:expr) => { fn bar() { $ i * 3; } }
316 ($ i:expr) => { fn bar() { $ i * 3; } }
336 // INT_NUMBER@8..9 "1"
339 // INT_NUMBER@10..11 "2"
342 // INT_NUMBER@12..13 "3"
343 // SEMICOLON@13..14 ";"
344 // R_CURLY@14..15 "}"
351 fn test_match_group_with_multichar_sep() {
355 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
357 m! (fn baz { true false } );
361 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
372 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
374 m! (fn baz { true && false } );
378 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
388 fn test_match_group_zero_match() {
391 macro_rules! m { ( $($i:ident)* ) => (); }
395 macro_rules! m { ( $($i:ident)* ) => (); }
402 fn test_match_group_in_group() {
406 [ $( ( $($i:ident)* ) )* ] => [ x![$( ( $($i)* ) )*]; ]
412 [ $( ( $($i:ident)* ) )* ] => [ x![$( ( $($i)* ) )*]; ]
420 fn test_expand_to_item_list() {
423 macro_rules! structs {
424 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
431 macro_rules! structs {
432 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
443 // STRUCT_KW@0..6 "struct"
446 // RECORD_FIELD_LIST@9..20
448 // RECORD_FIELD@10..19
450 // IDENT@10..15 "field"
454 // PATH_SEGMENT@16..19
456 // IDENT@16..19 "u32"
457 // R_CURLY@19..20 "}"
459 // STRUCT_KW@20..26 "struct"
461 // IDENT@26..29 "Bar"
462 // RECORD_FIELD_LIST@29..40
463 // L_CURLY@29..30 "{"
464 // RECORD_FIELD@30..39
466 // IDENT@30..35 "field"
470 // PATH_SEGMENT@36..39
472 // IDENT@36..39 "u32"
473 // R_CURLY@39..40 "}"
480 fn test_two_idents() {
484 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
490 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
501 fn test_tt_to_stmts() {
538 // INT_NUMBER@5..6 "0"
539 // SEMICOLON@6..7 ";"
550 // INT_NUMBER@9..11 "10"
553 // INT_NUMBER@12..13 "1"
554 // SEMICOLON@13..14 ";"
557 // PATH_SEGMENT@14..15
567 fn test_match_literal() {
571 ('(') => { fn l_paren() {} }
577 ('(') => { fn l_paren() {} }
585 fn test_parse_macro_def_simple() {
586 cov_mark::check!(parse_macro_def_simple);
589 macro m($id:ident) { fn $id() {} }
593 macro m($id:ident) { fn $id() {} }
600 fn test_parse_macro_def_rules() {
601 cov_mark::check!(parse_macro_def_rules);
606 ($id:ident) => { fn $id() {} }
612 ($id:ident) => { fn $id() {} }
620 fn test_macro_2_0_panic_2015() {
644 ($p:path) => { fn foo() { let a = $p; } }
649 m! { bar::<u8>::baz::<u8> }
653 ($p:path) => { fn foo() { let a = $p; } }
661 let a = bar::<u8>::baz::<u8> ;
668 fn test_two_paths() {
672 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
678 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
689 fn test_path_with_path() {
693 ($p:path) => { fn foo() { let a = $p::bar; } }
699 ($p:path) => { fn foo() { let a = $p::bar; } }
713 ($e:expr) => { fn bar() { $e; } }
716 m! { 2 + 2 * baz(3).quux() }
720 ($e:expr) => { fn bar() { $e; } }
731 fn test_last_expr() {
735 ($($item:expr),*) => {{
736 let mut v = Vec::new();
748 ($($item:expr),*) => {{
749 let mut v = Vec::new();
757 let mut v = Vec::new();
769 fn test_expr_with_attr() {
772 macro_rules! m { ($a:expr) => { x!(); } }
776 macro_rules! m { ($a:expr) => { x!(); } }
787 ($t:ty) => ( fn bar() -> $t {} )
793 ($t:ty) => ( fn bar() -> $t {} )
795 fn bar() -> Baz<u8> {}
801 fn test_ty_with_complex_type() {
805 ($t:ty) => ( fn bar() -> $ t {} )
810 m! { extern "Rust" fn() -> Ret }
814 ($t:ty) => ( fn bar() -> $ t {} )
817 fn bar() -> & 'a Baz<u8> {}
819 fn bar() -> extern "Rust"fn() -> Ret {}
829 ($p:pat) => { fn foo() { let $p; } }
835 ($p:pat) => { fn foo() { let $p; } }
849 ($s:stmt) => ( fn bar() { $s; } )
856 ($s:stmt) => ( fn bar() { $s; } )
869 fn test_single_item() {
872 macro_rules! m { ($i:item) => ( $i ) }
876 macro_rules! m { ($i:item) => ( $i ) }
883 fn test_all_items() {
886 macro_rules! m { ($($i:item)*) => ($($i )*) }
904 macro_rules! m { ($($i:item)*) => ($($i )*) }
928 macro_rules! m { ($b:block) => { fn foo() $b } }
932 macro_rules! m { ($b:block) => { fn foo() $b } }
945 ($m:meta) => ( #[$m] fn bar() {} )
947 m! { cfg(target_os = "windows") }
952 ($m:meta) => ( #[$m] fn bar() {} )
954 #[cfg(target_os = "windows")] fn bar() {}
955 #[hello::world] fn bar() {}
961 fn test_meta_doc_comments() {
962 cov_mark::check!(test_meta_doc_comments);
966 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
969 /// Single Line Doc 1
977 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
979 #[doc = " Single Line Doc 1"]
980 #[doc = "\n MultiLines Doc\n "] fn bar() {}
986 fn test_meta_extended_key_value_attributes() {
990 (#[$m:meta]) => ( #[$m] fn bar() {} )
992 m! { #[doc = concat!("The `", "bla", "` lang item.")] }
996 (#[$m:meta]) => ( #[$m] fn bar() {} )
998 #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {}
1004 fn test_meta_doc_comments_non_latin() {
1008 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1011 /// 錦瑟無端五十弦,一弦一柱思華年。
1019 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1021 #[doc = " 錦瑟無端五十弦,一弦一柱思華年。"]
1022 #[doc = "\n 莊生曉夢迷蝴蝶,望帝春心託杜鵑。\n "] fn bar() {}
1028 fn test_meta_doc_comments_escaped_characters() {
1032 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1040 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1042 #[doc = " \\ \" \'"] fn bar() {}