1 //! Tests specific to declarative macros, aka macros by example. This covers
2 //! both stable `macro_rules!` macros as well as unstable `macro` macros.
9 use expect_test::expect;
11 use crate::macro_expansion_tests::check;
17 macro_rules! impl_froms {
18 ($e:ident: $($v:ident),*) => {
20 impl From<$v> for $e {
21 fn from(it: $v) -> $e { $e::$v(it) }
26 impl_froms!(TokenTree: Leaf, Subtree);
29 macro_rules! impl_froms {
30 ($e:ident: $($v:ident),*) => {
32 impl From<$v> for $e {
33 fn from(it: $v) -> $e { $e::$v(it) }
38 impl From<Leaf> for TokenTree {
39 fn from(it: Leaf) -> TokenTree {
43 impl From<Subtree> for TokenTree {
44 fn from(it: Subtree) -> TokenTree {
45 TokenTree::Subtree(it)
53 fn expansion_does_not_parse_as_expression() {
60 fn f() { let _ = stmts!(); }
67 fn f() { let _ = /* error: could not convert tokens */; }
73 fn wrong_nesting_level() {
77 ($($i:ident);*) => ($i)
83 ($($i:ident);*) => ($i)
85 /* error: expected simple binding, found nested binding `i` */
91 fn match_by_first_token_literally() {
95 ($i:ident) => ( mod $i {} );
96 (= $i:ident) => ( fn $i() {} );
97 (+ $i:ident) => ( struct $i; )
105 ($i:ident) => ( mod $i {} );
106 (= $i:ident) => ( fn $i() {} );
107 (+ $i:ident) => ( struct $i; )
117 fn match_by_last_token_literally() {
121 ($i:ident) => ( mod $i {} );
122 ($i:ident =) => ( fn $i() {} );
123 ($i:ident +) => ( struct $i; )
131 ($i:ident) => ( mod $i {} );
132 ($i:ident =) => ( fn $i() {} );
133 ($i:ident +) => ( struct $i; )
143 fn match_by_ident() {
147 ($i:ident) => ( mod $i {} );
148 (spam $i:ident) => ( fn $i() {} );
149 (eggs $i:ident) => ( struct $i; )
157 ($i:ident) => ( mod $i {} );
158 (spam $i:ident) => ( fn $i() {} );
159 (eggs $i:ident) => ( struct $i; )
169 fn match_by_separator_token() {
173 ($($i:ident),*) => ($(mod $i {} )*);
174 ($($i:ident)#*) => ($(fn $i() {} )*);
175 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
186 ($($i:ident),*) => ($(mod $i {} )*);
187 ($($i:ident)#*) => ($(fn $i() {} )*);
188 ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
204 fn test_match_group_pattern_with_multiple_defs() {
208 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
214 ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
225 fn test_match_group_pattern_with_multiple_statement() {
229 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
235 ($($i:ident),*) => ( fn baz() { $($i ();)* } );
246 fn test_match_group_pattern_with_multiple_statement_without_semi() {
250 ($($i:ident),*) => ( fn baz() { $($i() );* } );
256 ($($i:ident),*) => ( fn baz() { $($i() );* } );
267 fn test_match_group_empty_fixed_token() {
271 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
277 ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
285 fn test_match_group_in_subtree() {
289 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
291 m! { fn baz { a b } }
295 (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
306 fn test_expr_order() {
310 ($ i:expr) => { fn bar() { $ i * 3; } }
317 ($ i:expr) => { fn bar() { $ i * 3; } }
337 // INT_NUMBER@8..9 "1"
340 // INT_NUMBER@10..11 "2"
343 // INT_NUMBER@12..13 "3"
344 // SEMICOLON@13..14 ";"
345 // R_CURLY@14..15 "}"
352 fn test_match_group_with_multichar_sep() {
356 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
358 m! (fn baz { true false } );
362 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
373 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
375 m! (fn baz { true && false } );
379 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
389 fn test_match_group_zero_match() {
392 macro_rules! m { ( $($i:ident)* ) => (); }
396 macro_rules! m { ( $($i:ident)* ) => (); }
403 fn test_match_group_in_group() {
407 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
413 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
421 fn test_expand_to_item_list() {
424 macro_rules! structs {
425 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
432 macro_rules! structs {
433 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
444 // STRUCT_KW@0..6 "struct"
447 // RECORD_FIELD_LIST@9..20
449 // RECORD_FIELD@10..19
451 // IDENT@10..15 "field"
455 // PATH_SEGMENT@16..19
457 // IDENT@16..19 "u32"
458 // R_CURLY@19..20 "}"
460 // STRUCT_KW@20..26 "struct"
462 // IDENT@26..29 "Bar"
463 // RECORD_FIELD_LIST@29..40
464 // L_CURLY@29..30 "{"
465 // RECORD_FIELD@30..39
467 // IDENT@30..35 "field"
471 // PATH_SEGMENT@36..39
473 // IDENT@36..39 "u32"
474 // R_CURLY@39..40 "}"
481 fn test_two_idents() {
485 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
491 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
502 fn test_tt_to_stmts() {
539 // INT_NUMBER@5..6 "0"
540 // SEMICOLON@6..7 ";"
551 // INT_NUMBER@9..11 "10"
554 // INT_NUMBER@12..13 "1"
555 // SEMICOLON@13..14 ";"
558 // PATH_SEGMENT@14..15
568 fn test_match_literal() {
572 ('(') => { fn l_paren() {} }
578 ('(') => { fn l_paren() {} }
586 fn test_parse_macro_def_simple() {
587 cov_mark::check!(parse_macro_def_simple);
590 macro m($id:ident) { fn $id() {} }
594 macro m($id:ident) { fn $id() {} }
601 fn test_parse_macro_def_rules() {
602 cov_mark::check!(parse_macro_def_rules);
607 ($id:ident) => { fn $id() {} }
613 ($id:ident) => { fn $id() {} }
621 fn test_macro_2_0_panic_2015() {
645 ($p:path) => { fn foo() { let a = $p; } }
650 m! { bar::<u8>::baz::<u8> }
654 ($p:path) => { fn foo() { let a = $p; } }
662 let a = bar::<u8>::baz::<u8> ;
669 fn test_two_paths() {
673 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
679 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
690 fn test_path_with_path() {
694 ($p:path) => { fn foo() { let a = $p::bar; } }
700 ($p:path) => { fn foo() { let a = $p::bar; } }
714 ($e:expr) => { fn bar() { $e; } }
717 m! { 2 + 2 * baz(3).quux() }
721 ($e:expr) => { fn bar() { $e; } }
732 fn test_last_expr() {
736 ($($item:expr),*) => {{
737 let mut v = Vec::new();
749 ($($item:expr),*) => {{
750 let mut v = Vec::new();
758 let mut v = Vec::new();
770 fn test_expr_with_attr() {
773 macro_rules! m { ($a:expr) => { ok!(); } }
777 macro_rules! m { ($a:expr) => { ok!(); } }
788 ($t:ty) => ( fn bar() -> $t {} )
794 ($t:ty) => ( fn bar() -> $t {} )
796 fn bar() -> Baz<u8> {}
802 fn test_ty_with_complex_type() {
806 ($t:ty) => ( fn bar() -> $ t {} )
811 m! { extern "Rust" fn() -> Ret }
815 ($t:ty) => ( fn bar() -> $ t {} )
818 fn bar() -> & 'a Baz<u8> {}
820 fn bar() -> extern "Rust"fn() -> Ret {}
830 ($p:pat) => { fn foo() { let $p; } }
836 ($p:pat) => { fn foo() { let $p; } }
850 ($s:stmt) => ( fn bar() { $s; } )
857 ($s:stmt) => ( fn bar() { $s; } )
870 fn test_single_item() {
873 macro_rules! m { ($i:item) => ( $i ) }
877 macro_rules! m { ($i:item) => ( $i ) }
884 fn test_all_items() {
887 macro_rules! m { ($($i:item)*) => ($($i )*) }
905 macro_rules! m { ($($i:item)*) => ($($i )*) }
929 macro_rules! m { ($b:block) => { fn foo() $b } }
933 macro_rules! m { ($b:block) => { fn foo() $b } }
946 ($m:meta) => ( #[$m] fn bar() {} )
948 m! { cfg(target_os = "windows") }
953 ($m:meta) => ( #[$m] fn bar() {} )
955 #[cfg(target_os = "windows")] fn bar() {}
956 #[hello::world] fn bar() {}
962 fn test_meta_doc_comments() {
963 cov_mark::check!(test_meta_doc_comments);
967 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
970 /// Single Line Doc 1
978 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
980 #[doc = " Single Line Doc 1"]
981 #[doc = "\n MultiLines Doc\n "] fn bar() {}
987 fn test_meta_extended_key_value_attributes() {
991 (#[$m:meta]) => ( #[$m] fn bar() {} )
993 m! { #[doc = concat!("The `", "bla", "` lang item.")] }
997 (#[$m:meta]) => ( #[$m] fn bar() {} )
999 #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {}
1005 fn test_meta_doc_comments_non_latin() {
1009 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1012 /// 錦瑟無端五十弦,一弦一柱思華年。
1020 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1022 #[doc = " 錦瑟無端五十弦,一弦一柱思華年。"]
1023 #[doc = "\n 莊生曉夢迷蝴蝶,望帝春心託杜鵑。\n "] fn bar() {}
1029 fn test_meta_doc_comments_escaped_characters() {
1033 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1041 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1043 #[doc = " \\ \" \'"] fn bar() {}
1049 fn test_tt_block() {
1052 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1056 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1065 fn test_tt_group() {
1068 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1072 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1079 fn test_tt_composite() {
1082 macro_rules! m { ($tt:tt) => { ok!(); } }
1087 macro_rules! m { ($tt:tt) => { ok!(); } }
1089 /* error: leftover tokens */ok!();
1095 fn test_tt_composite2() {
1098 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1102 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1109 fn test_tt_with_composite_without_space() {
1110 // Test macro input without any spaces
1111 // See https://github.com/rust-analyzer/rust-analyzer/issues/6692
1114 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1118 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1125 fn test_underscore() {
1128 macro_rules! m { ($_:tt) => { ok!(); } }
1132 macro_rules! m { ($_:tt) => { ok!(); } }
1139 fn test_underscore_not_greedily() {
1142 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1144 ($($a:ident)* _) => { ok!(); }
1148 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1150 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1152 m2![a => b c => d _ => ou]
1155 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1157 ($($a:ident)* _) => { ok!(); }
1161 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1163 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1171 fn test_underscore_flavors() {
1174 macro_rules! m1 { ($a:ty) => { ok!(); } }
1177 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1181 macro_rules! m1 { ($a:ty) => { ok!(); } }
1184 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1191 fn test_vertical_bar_with_pat() {
1194 macro_rules! m { (|$pat:pat| ) => { ok!(); } }
1198 macro_rules! m { (|$pat:pat| ) => { ok!(); } }
1205 fn test_dollar_crate_lhs_is_not_meta() {
1209 ($crate) => { err!(); };
1216 ($crate) => { err!(); };
1225 fn test_lifetime() {
1229 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1235 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1249 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1255 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1257 const VALUE: u8 = 0;
1264 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1270 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1272 const VALUE: i32 = -1;
1278 fn test_boolean_is_ident() {
1282 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1288 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1290 const VALUE: (bool, bool) = (true , false );
1300 ($vis:vis $name:ident) => { $vis fn $name() {} }
1307 ($vis:vis $name:ident) => { $vis fn $name() {} }
1316 fn test_inner_macro_rules() {
1320 ($a:ident, $b:ident, $c:tt) => {
1321 macro_rules! inner {
1322 ($bi:ident) => { fn $bi() -> u8 { $c } }
1326 fn $b() -> u8 { $c }
1333 ($a:ident, $b:ident, $c:tt) => {
1334 macro_rules! inner {
1335 ($bi:ident) => { fn $bi() -> u8 { $c } }
1339 fn $b() -> u8 { $c }
1342 macro_rules !inner {
1358 fn test_expr_after_path_colons() {
1362 ($k:expr) => { fn f() { K::$k; } }
1369 ($k:expr) => { fn f() { K::$k; } }
1371 /* parse error: expected identifier */
1372 /* parse error: expected SEMICOLON */
1376 // MACRO_ITEMS@0..17
1391 // PATH_SEGMENT@6..7
1399 // PATH_SEGMENT@9..10
1403 // L_PAREN@10..11 "("
1405 // STRING@11..14 "\"0\""
1406 // R_PAREN@14..15 ")"
1407 // SEMICOLON@15..16 ";"
1408 // R_CURLY@16..17 "}"
1415 fn test_match_is_not_greedy() {
1419 ($($i:ident $(,)*),*) => {};
1425 ($($i:ident $(,)*),*) => {};
1433 fn expr_interpolation() {
1436 macro_rules! m { ($expr:expr) => { map($expr) } }
1438 let _ = m!(x + foo);
1442 macro_rules! m { ($expr:expr) => { map($expr) } }
1451 fn mbe_are_not_attributes() {
1454 macro_rules! error {
1462 macro_rules! error {