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; } }
339 // INT_NUMBER@9..10 "1"
342 // INT_NUMBER@11..12 "2"
343 // R_PAREN@12..13 ")"
346 // INT_NUMBER@14..15 "3"
347 // SEMICOLON@15..16 ";"
348 // R_CURLY@16..17 "}"
355 fn test_match_group_with_multichar_sep() {
359 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
361 m! (fn baz { true false } );
365 (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
376 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
378 m! (fn baz { true && false } );
382 (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
392 fn test_match_group_zero_match() {
395 macro_rules! m { ( $($i:ident)* ) => (); }
399 macro_rules! m { ( $($i:ident)* ) => (); }
406 fn test_match_group_in_group() {
410 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
416 [ $( ( $($i:ident)* ) )* ] => [ ok![$( ( $($i)* ) )*]; ]
424 fn test_expand_to_item_list() {
427 macro_rules! structs {
428 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
435 macro_rules! structs {
436 ($($i:ident),*) => { $(struct $i { field: u32 } )* }
447 // STRUCT_KW@0..6 "struct"
450 // RECORD_FIELD_LIST@9..20
452 // RECORD_FIELD@10..19
454 // IDENT@10..15 "field"
458 // PATH_SEGMENT@16..19
460 // IDENT@16..19 "u32"
461 // R_CURLY@19..20 "}"
463 // STRUCT_KW@20..26 "struct"
465 // IDENT@26..29 "Bar"
466 // RECORD_FIELD_LIST@29..40
467 // L_CURLY@29..30 "{"
468 // RECORD_FIELD@30..39
470 // IDENT@30..35 "field"
474 // PATH_SEGMENT@36..39
476 // IDENT@36..39 "u32"
477 // R_CURLY@39..40 "}"
484 fn test_two_idents() {
488 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
494 ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
505 fn test_tt_to_stmts() {
542 // INT_NUMBER@5..6 "0"
543 // SEMICOLON@6..7 ";"
554 // INT_NUMBER@9..11 "10"
557 // INT_NUMBER@12..13 "1"
558 // SEMICOLON@13..14 ";"
561 // PATH_SEGMENT@14..15
571 fn test_match_literal() {
575 ('(') => { fn l_paren() {} }
581 ('(') => { fn l_paren() {} }
589 fn test_parse_macro_def_simple() {
590 cov_mark::check!(parse_macro_def_simple);
593 macro m($id:ident) { fn $id() {} }
597 macro m($id:ident) { fn $id() {} }
604 fn test_parse_macro_def_rules() {
605 cov_mark::check!(parse_macro_def_rules);
610 ($id:ident) => { fn $id() {} }
616 ($id:ident) => { fn $id() {} }
624 fn test_macro_2_0_panic_2015() {
648 ($p:path) => { fn foo() { let a = $p; } }
653 m! { bar::<u8>::baz::<u8> }
657 ($p:path) => { fn foo() { let a = $p; } }
665 let a = bar::<u8>::baz::<u8> ;
672 fn test_two_paths() {
676 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
682 ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
693 fn test_path_with_path() {
697 ($p:path) => { fn foo() { let a = $p::bar; } }
703 ($p:path) => { fn foo() { let a = $p::bar; } }
717 ($e:expr) => { fn bar() { $e; } }
720 m! { 2 + 2 * baz(3).quux() }
724 ($e:expr) => { fn bar() { $e; } }
735 fn test_last_expr() {
739 ($($item:expr),*) => {{
740 let mut v = Vec::new();
752 ($($item:expr),*) => {{
753 let mut v = Vec::new();
761 let mut v = Vec::new();
773 fn test_expr_with_attr() {
776 macro_rules! m { ($a:expr) => { ok!(); } }
780 macro_rules! m { ($a:expr) => { ok!(); } }
791 ($t:ty) => ( fn bar() -> $t {} )
797 ($t:ty) => ( fn bar() -> $t {} )
799 fn bar() -> Baz<u8> {}
805 fn test_ty_with_complex_type() {
809 ($t:ty) => ( fn bar() -> $ t {} )
814 m! { extern "Rust" fn() -> Ret }
818 ($t:ty) => ( fn bar() -> $ t {} )
821 fn bar() -> & 'a Baz<u8> {}
823 fn bar() -> extern "Rust"fn() -> Ret {}
833 ($p:pat) => { fn foo() { let $p; } }
839 ($p:pat) => { fn foo() { let $p; } }
853 ($s:stmt) => ( fn bar() { $s; } )
860 ($s:stmt) => ( fn bar() { $s; } )
873 fn test_single_item() {
876 macro_rules! m { ($i:item) => ( $i ) }
880 macro_rules! m { ($i:item) => ( $i ) }
887 fn test_all_items() {
890 macro_rules! m { ($($i:item)*) => ($($i )*) }
908 macro_rules! m { ($($i:item)*) => ($($i )*) }
932 macro_rules! m { ($b:block) => { fn foo() $b } }
936 macro_rules! m { ($b:block) => { fn foo() $b } }
949 ($m:meta) => ( #[$m] fn bar() {} )
951 m! { cfg(target_os = "windows") }
956 ($m:meta) => ( #[$m] fn bar() {} )
958 #[cfg(target_os = "windows")] fn bar() {}
959 #[hello::world] fn bar() {}
965 fn test_meta_doc_comments() {
966 cov_mark::check!(test_meta_doc_comments);
970 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
973 /// Single Line Doc 1
981 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
983 #[doc = " Single Line Doc 1"]
984 #[doc = "\n MultiLines Doc\n "] fn bar() {}
990 fn test_meta_extended_key_value_attributes() {
994 (#[$m:meta]) => ( #[$m] fn bar() {} )
996 m! { #[doc = concat!("The `", "bla", "` lang item.")] }
1000 (#[$m:meta]) => ( #[$m] fn bar() {} )
1002 #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {}
1008 fn test_meta_doc_comments_non_latin() {
1012 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1015 /// 錦瑟無端五十弦,一弦一柱思華年。
1023 ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1025 #[doc = " 錦瑟無端五十弦,一弦一柱思華年。"]
1026 #[doc = "\n 莊生曉夢迷蝴蝶,望帝春心託杜鵑。\n "] fn bar() {}
1032 fn test_meta_doc_comments_escaped_characters() {
1036 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1044 ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1046 #[doc = " \\ \" \'"] fn bar() {}
1052 fn test_tt_block() {
1055 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1059 macro_rules! m { ($tt:tt) => { fn foo() $tt } }
1068 fn test_tt_group() {
1071 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1075 macro_rules! m { ($($tt:tt)*) => { $($tt)* } }
1082 fn test_tt_composite() {
1085 macro_rules! m { ($tt:tt) => { ok!(); } }
1090 macro_rules! m { ($tt:tt) => { ok!(); } }
1092 /* error: leftover tokens */ok!();
1098 fn test_tt_composite2() {
1101 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1105 macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } }
1112 fn test_tt_with_composite_without_space() {
1113 // Test macro input without any spaces
1114 // See https://github.com/rust-analyzer/rust-analyzer/issues/6692
1117 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1121 macro_rules! m { ($ op:tt, $j:path) => ( ok!(); ) }
1128 fn test_underscore() {
1131 macro_rules! m { ($_:tt) => { ok!(); } }
1135 macro_rules! m { ($_:tt) => { ok!(); } }
1142 fn test_underscore_not_greedily() {
1145 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1147 ($($a:ident)* _) => { ok!(); }
1151 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1153 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1155 m2![a => b c => d _ => ou]
1158 // `_` overlaps with `$a:ident` but rustc matches it under the `_` token.
1160 ($($a:ident)* _) => { ok!(); }
1164 // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`.
1166 ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); }
1174 fn test_underscore_flavors() {
1177 macro_rules! m1 { ($a:ty) => { ok!(); } }
1180 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1184 macro_rules! m1 { ($a:ty) => { ok!(); } }
1187 macro_rules! m2 { ($a:lifetime) => { ok!(); } }
1194 fn test_vertical_bar_with_pat() {
1197 macro_rules! m { (|$pat:pat| ) => { ok!(); } }
1201 macro_rules! m { (|$pat:pat| ) => { ok!(); } }
1208 fn test_dollar_crate_lhs_is_not_meta() {
1212 ($crate) => { err!(); };
1219 ($crate) => { err!(); };
1228 fn test_lifetime() {
1232 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1238 ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } }
1252 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1258 ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; };
1260 const VALUE: u8 = 0;
1267 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1273 ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; };
1275 const VALUE: i32 = -1;
1281 fn test_boolean_is_ident() {
1285 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1291 ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); };
1293 const VALUE: (bool, bool) = (true , false );
1303 ($vis:vis $name:ident) => { $vis fn $name() {} }
1310 ($vis:vis $name:ident) => { $vis fn $name() {} }
1319 fn test_inner_macro_rules() {
1323 ($a:ident, $b:ident, $c:tt) => {
1324 macro_rules! inner {
1325 ($bi:ident) => { fn $bi() -> u8 { $c } }
1329 fn $b() -> u8 { $c }
1336 ($a:ident, $b:ident, $c:tt) => {
1337 macro_rules! inner {
1338 ($bi:ident) => { fn $bi() -> u8 { $c } }
1342 fn $b() -> u8 { $c }
1345 macro_rules !inner {
1361 fn test_expr_after_path_colons() {
1365 ($k:expr) => { fn f() { K::$k; } }
1372 ($k:expr) => { fn f() { K::$k; } }
1374 /* parse error: expected identifier */
1375 /* parse error: expected SEMICOLON */
1376 /* parse error: expected SEMICOLON */
1377 /* parse error: expected expression */
1381 // MACRO_ITEMS@0..19
1396 // PATH_SEGMENT@6..7
1401 // L_PAREN@9..10 "("
1406 // PATH_SEGMENT@10..11
1410 // L_PAREN@11..12 "("
1412 // STRING@12..15 "\"0\""
1413 // R_PAREN@15..16 ")"
1415 // R_PAREN@16..17 ")"
1416 // SEMICOLON@17..18 ";"
1417 // R_CURLY@18..19 "}"
1424 fn test_match_is_not_greedy() {
1428 ($($i:ident $(,)*),*) => {};
1434 ($($i:ident $(,)*),*) => {};
1442 fn expr_interpolation() {
1445 macro_rules! m { ($expr:expr) => { map($expr) } }
1447 let _ = m!(x + foo);
1451 macro_rules! m { ($expr:expr) => { map($expr) } }
1453 let _ = map((x+foo));
1460 fn mbe_are_not_attributes() {
1463 macro_rules! error {
1471 macro_rules! error {