From 5a854a72539c14c90daf6e0385fa6f72b53aacd5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 12:39:58 +0300 Subject: [PATCH 01/22] internal: move tests --- .../hir_def/src/macro_expansion_tests/mbe.rs | 66 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 54 --------------- crates/test_utils/src/fixture.rs | 1 + 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index df93298a3561..dcd0a8880b8a 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1119,3 +1119,69 @@ ok!(); "#]], ); } + +#[test] +fn test_underscore() { + check( + r#" +macro_rules! m { ($_:tt) => { ok!(); } } +m! { => } +"#, + expect![[r#" +macro_rules! m { ($_:tt) => { ok!(); } } +ok!(); +"#]], + ); +} + +#[test] +fn test_underscore_not_greedily() { + check( + r#" +// `_` overlaps with `$a:ident` but rustc matches it under the `_` token. +macro_rules! m1 { + ($($a:ident)* _) => { ok!(); } +} +m1![a b c d _]; + +// `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`. +macro_rules! m2 { + ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); } +} +m2![a => b c => d _ => ou] +"#, + expect![[r#" +// `_` overlaps with `$a:ident` but rustc matches it under the `_` token. +macro_rules! m1 { + ($($a:ident)* _) => { ok!(); } +} +ok!(); + +// `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`. +macro_rules! m2 { + ($($a:expr => $b:ident)* _ => $c:expr) => { ok!(); } +} +ok!(); +"#]], + ); +} + +#[test] +fn test_underscore_flavors() { + check( + r#" +macro_rules! m1 { ($a:ty) => { ok!(); } } +m1![_]; + +macro_rules! m2 { ($a:lifetime) => { ok!(); } } +m2!['_]; +"#, + expect![[r#" +macro_rules! m1 { ($a:ty) => { ok!(); } } +ok!(); + +macro_rules! m2 { ($a:lifetime) => { ok!(); } } +ok!(); +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 15a718402911..52a218ed1168 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -101,60 +101,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_underscore() { - parse_macro( - r#" - macro_rules! foo { - ($_:tt) => { 0 } - } - "#, - ) - .assert_expand_items(r#"foo! { => }"#, r#"0"#); -} - -#[test] -fn test_underscore_not_greedily() { - parse_macro( - r#" -macro_rules! q { - ($($a:ident)* _) => {0}; -} -"#, - ) - // `_` overlaps with `$a:ident` but rustc matches it under the `_` token - .assert_expand_items(r#"q![a b c d _]"#, r#"0"#); - - parse_macro( - r#" -macro_rules! q { - ($($a:expr => $b:ident)* _ => $c:expr) => {0}; -} -"#, - ) - // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr` - .assert_expand_items(r#"q![a => b c => d _ => ou]"#, r#"0"#); -} - -#[test] -fn test_underscore_as_type() { - parse_macro( - r#" -macro_rules! q { - ($a:ty) => {0}; -} -"#, - ) - // Underscore is a type - .assert_expand_items(r#"q![_]"#, r#"0"#); -} - -#[test] -fn test_underscore_lifetime() { - parse_macro(r#"macro_rules! q { ($a:lifetime) => {0}; }"#) - .assert_expand_items(r#"q!['_]"#, r#"0"#); -} - #[test] fn test_vertical_bar_with_pat() { parse_macro( diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index 5ea7a994b4fc..3d303a1237d0 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs @@ -147,6 +147,7 @@ impl Fixture { if line.starts_with("// ") && line.contains(':') && !line.contains("::") + && !line.contains(".") && line.chars().all(|it| !it.is_uppercase()) { panic!("looks like invalid metadata line: {:?}", line); From 6fd2f1d25b807a72660034dd05e80abf3c462594 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 12:45:17 +0300 Subject: [PATCH 02/22] internal: move tests --- .../hir_def/src/macro_expansion_tests/mbe.rs | 54 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 37 ------------- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index dcd0a8880b8a..dc6ab36b7612 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1185,3 +1185,57 @@ ok!(); "#]], ); } + +#[test] +fn test_vertical_bar_with_pat() { + check( + r#" +macro_rules! m { (|$pat:pat| ) => { ok!(); } } +m! { |x| } + "#, + expect![[r#" +macro_rules! m { (|$pat:pat| ) => { ok!(); } } +ok!(); + "#]], + ); +} + +#[test] +fn test_dollar_crate_lhs_is_not_meta() { + check( + r#" +macro_rules! m { + ($crate) => { err!(); }; + () => { ok!(); }; +} +m!{} +"#, + expect![[r#" +macro_rules! m { + ($crate) => { err!(); }; + () => { ok!(); }; +} +ok!(); +"#]], + ); +} + +#[test] +fn test_lifetime() { + check( + r#" +macro_rules! m { + ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } } +} +m! {'a} +"#, + expect![[r#" +macro_rules! m { + ($lt:lifetime) => { struct Ref<$lt>{ s: &$ lt str } } +} +struct Ref<'a> { + s: &'a str +} +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 52a218ed1168..8dd1f3311945 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -101,43 +101,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_vertical_bar_with_pat() { - parse_macro( - r#" - macro_rules! foo { - (| $pat:pat | ) => { 0 } - } - "#, - ) - .assert_expand_items(r#"foo! { | x | }"#, r#"0"#); -} - -#[test] -fn test_dollar_crate_lhs_is_not_meta() { - parse_macro( - r#" -macro_rules! foo { - ($crate) => {}; - () => {0}; -} - "#, - ) - .assert_expand_items(r#"foo!{}"#, r#"0"#); -} - -#[test] -fn test_lifetime() { - parse_macro( - r#" - macro_rules! foo { - ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } - } -"#, - ) - .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); -} - #[test] fn test_literal() { parse_macro( From 748e6881fc528cdafb0a0c257b0e00a7d1f495bb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 12:52:28 +0300 Subject: [PATCH 03/22] move tests --- crates/hir_def/src/macro_expansion_tests.rs | 2 +- .../hir_def/src/macro_expansion_tests/mbe.rs | 45 ++++++++++++++++--- crates/mbe/src/tests/expand.rs | 21 --------- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index 66874a674d82..d113a2f504b4 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -128,7 +128,7 @@ fn pretty_print_macro_expansion(expn: SyntaxNode) -> String { (T![>], _) if curr_kind.is_keyword() => " ", (T![->], _) | (_, T![->]) => " ", (T![&&], _) | (_, T![&&]) => " ", - (T![,], _) => " ", + (T![,] | T![:], _) => " ", (T![fn], T!['(']) => "", (T![']'], _) if curr_kind.is_keyword() => " ", (T![']'], T![#]) => "\n", diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index dc6ab36b7612..3ac8f706b6ed 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -35,12 +35,12 @@ macro_rules! impl_froms { } } impl From for TokenTree { - fn from(it:Leaf) -> TokenTree { + fn from(it: Leaf) -> TokenTree { TokenTree::Leaf(it) } } impl From for TokenTree { - fn from(it:Subtree) -> TokenTree { + fn from(it: Subtree) -> TokenTree { TokenTree::Subtree(it) } } @@ -433,10 +433,10 @@ macro_rules! structs { } struct Foo { - field:u32 + field: u32 } struct Bar { - field:u32 + field: u32 } // MACRO_ITEMS@0..40 // STRUCT@0..20 @@ -906,8 +906,8 @@ extern crate a; mod b; mod c {} use d; -const E:i32 = 0; -static F:i32 = 0; +const E: i32 = 0; +static F: i32 = 0; impl G {} struct H; enum I { @@ -1239,3 +1239,36 @@ struct Ref<'a> { "#]], ); } + +#[test] +fn test_literal() { + check( + r#" +macro_rules! m { + ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; }; +} +m!(u8, 0); +"#, + expect![[r#" +macro_rules! m { + ($type:ty, $lit:literal) => { const VALUE: $type = $ lit; }; +} +const VALUE: u8 = 0; +"#]], + ); + + check( + r#" +macro_rules! m { + ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; }; +} +m!(i32, -1); +"#, + expect![[r#" +macro_rules! m { + ($type:ty, $lit:literal) => { const VALUE: $ type = $ lit; }; +} +const VALUE: i32 = -1; +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 8dd1f3311945..67543df5838c 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -101,27 +101,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_literal() { - parse_macro( - r#" - macro_rules! foo { - ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;}; - } -"#, - ) - .assert_expand_items(r#"foo!(u8,0);"#, r#"const VALUE : u8 = 0 ;"#); - - parse_macro( - r#" - macro_rules! foo { - ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;}; - } -"#, - ) - .assert_expand_items(r#"foo!(i32,-1);"#, r#"const VALUE : i32 = - 1 ;"#); -} - #[test] fn test_boolean_is_ident() { parse_macro( From 7d92b9f6ff039e8f8dc67bed2c830950e230f870 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 12:55:31 +0300 Subject: [PATCH 04/22] move test --- .../hir_def/src/macro_expansion_tests/mbe.rs | 18 +++++++++++ crates/mbe/src/tests/expand.rs | 30 ------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 3ac8f706b6ed..1cad690bee06 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1272,3 +1272,21 @@ const VALUE: i32 = -1; "#]], ); } + +#[test] +fn test_boolean_is_ident() { + check( + r#" +macro_rules! m { + ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); }; +} +m!(true, false); +"#, + expect![[r#" +macro_rules! m { + ($lit0:literal, $lit1:literal) => { const VALUE: (bool, bool) = ($lit0, $lit1); }; +} +const VALUE: (bool, bool) = (true , false ); +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 67543df5838c..306db3c085fa 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -101,36 +101,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_boolean_is_ident() { - parse_macro( - r#" - macro_rules! foo { - ($lit0:literal, $lit1:literal) => { const VALUE: (bool,bool) = ($lit0,$lit1); }; - } -"#, - ) - .assert_expand( - r#"foo!(true,false);"#, - r#" -SUBTREE $ - IDENT const 14 - IDENT VALUE 15 - PUNCH : [alone] 16 - SUBTREE () 17 - IDENT bool 18 - PUNCH , [alone] 19 - IDENT bool 20 - PUNCH = [alone] 21 - SUBTREE () 22 - IDENT true 29 - PUNCH , [joint] 25 - IDENT false 31 - PUNCH ; [alone] 28 -"#, - ); -} - #[test] fn test_vis() { parse_macro( From 8670e83cecea6a18d3de58d83a8f82c217470c08 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 12:57:18 +0300 Subject: [PATCH 05/22] move test --- .../hir_def/src/macro_expansion_tests/mbe.rs | 20 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 14 ------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 1cad690bee06..4ed46a132543 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1290,3 +1290,23 @@ const VALUE: (bool, bool) = (true , false ); "#]], ); } + +#[test] +fn test_vis() { + check( + r#" +macro_rules! m { + ($vis:vis $name:ident) => { $vis fn $name() {} } +} +m!(pub foo); +m!(foo); +"#, + expect![[r#" +macro_rules! m { + ($vis:vis $name:ident) => { $vis fn $name() {} } +} +pub fn foo() {} +fn foo() {} +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 306db3c085fa..51c3ba10da13 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -101,20 +101,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_vis() { - parse_macro( - r#" - macro_rules! foo { - ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; - } -"#, - ) - .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#) - // test optional cases - .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#); -} - #[test] fn test_inner_macro_rules() { parse_macro( From e255e9577f672fb6aff6004a88ed3e520f6c8326 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:21:42 +0300 Subject: [PATCH 06/22] internal: move test --- crates/hir_def/src/macro_expansion_tests.rs | 29 +++-- .../hir_def/src/macro_expansion_tests/mbe.rs | 117 ++++++++++++++++++ crates/mbe/src/tests/expand.rs | 58 +-------- 3 files changed, 140 insertions(+), 64 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index d113a2f504b4..f9527a41358d 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -20,7 +20,7 @@ use stdx::format_to; use syntax::{ ast::{self, edit::IndentLevel}, AstNode, - SyntaxKind::{EOF, IDENT, LIFETIME_IDENT}, + SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT}, SyntaxNode, T, }; @@ -60,21 +60,36 @@ fn check(ra_fixture: &str, mut expect: Expect) { let mut expanded_text = source_file.to_string(); for (call, exp) in expansions.into_iter().rev() { + let mut tree = false; + let mut expect_errors = false; + for comment in call.syntax().children_with_tokens().filter(|it| it.kind() == COMMENT) { + tree |= comment.to_string().contains("+tree"); + expect_errors |= comment.to_string().contains("+errors"); + } + let mut expn_text = String::new(); if let Some(err) = exp.err { format_to!(expn_text, "/* error: {} */", err); } if let Some((parse, _token_map)) = exp.value { - assert!( - parse.errors().is_empty(), - "parse errors in expansion: \n{:#?}", - parse.errors() - ); + if expect_errors { + assert!(!parse.errors().is_empty(), "no parse errors in expansion"); + for e in parse.errors() { + format_to!(expn_text, "/* parse error: {} */\n", e); + } + } else { + assert!( + parse.errors().is_empty(), + "parse errors in expansion: \n{:#?}", + parse.errors() + ); + } let pp = pretty_print_macro_expansion(parse.syntax_node()); let indent = IndentLevel::from_node(call.syntax()); let pp = reindent(indent, pp); format_to!(expn_text, "{}", pp); - if call.to_string().contains("// +tree") { + + if tree { let tree = format!("{:#?}", parse.syntax_node()) .split_inclusive("\n") .map(|line| format!("// {}", line)) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 4ed46a132543..7600b16ded75 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1310,3 +1310,120 @@ fn foo() {} "#]], ); } + +#[test] +fn test_inner_macro_rules() { + check( + r#" +macro_rules! m { + ($a:ident, $b:ident, $c:tt) => { + macro_rules! inner { + ($bi:ident) => { fn $bi() -> u8 { $c } } + } + + inner!($a); + fn $b() -> u8 { $c } + } +} +m!(x, y, 1); +"#, + expect![[r#" +macro_rules! m { + ($a:ident, $b:ident, $c:tt) => { + macro_rules! inner { + ($bi:ident) => { fn $bi() -> u8 { $c } } + } + + inner!($a); + fn $b() -> u8 { $c } + } +} +macro_rules !inner { + ($bi: ident) = > { + fn $bi()-> u8 { + 1 + } + } +} +inner!(x); +fn y() -> u8 { + 1 +} +"#]], + ); +} + +#[test] +fn test_expr_after_path_colons() { + check( + r#" +macro_rules! m { + ($k:expr) => { fn f() { K::$k; } } +} +// +tree +errors +m!(C("0")); +"#, + expect![[r#" +macro_rules! m { + ($k:expr) => { fn f() { K::$k; } } +} +/* parse error: expected identifier */ +/* parse error: expected SEMICOLON */ +fn f() { + K::C("0"); +} +// MACRO_ITEMS@0..17 +// FN@0..17 +// FN_KW@0..2 "fn" +// NAME@2..3 +// IDENT@2..3 "f" +// PARAM_LIST@3..5 +// L_PAREN@3..4 "(" +// R_PAREN@4..5 ")" +// BLOCK_EXPR@5..17 +// STMT_LIST@5..17 +// L_CURLY@5..6 "{" +// EXPR_STMT@6..9 +// PATH_EXPR@6..9 +// PATH@6..9 +// PATH@6..7 +// PATH_SEGMENT@6..7 +// NAME_REF@6..7 +// IDENT@6..7 "K" +// COLON2@7..9 "::" +// EXPR_STMT@9..16 +// CALL_EXPR@9..15 +// PATH_EXPR@9..10 +// PATH@9..10 +// PATH_SEGMENT@9..10 +// NAME_REF@9..10 +// IDENT@9..10 "C" +// ARG_LIST@10..15 +// L_PAREN@10..11 "(" +// LITERAL@11..14 +// STRING@11..14 "\"0\"" +// R_PAREN@14..15 ")" +// SEMICOLON@15..16 ";" +// R_CURLY@16..17 "}" + +"#]], + ); +} + +#[test] +fn test_match_is_not_greedy() { + check( + r#" +macro_rules! foo { + ($($i:ident $(,)*),*) => {}; +} +foo!(a,b); +"#, + expect![[r#" +macro_rules! foo { + ($($i:ident $(,)*),*) => {}; +} + +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 51c3ba10da13..79f0824b5946 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -1,8 +1,5 @@ use ::parser::ParserEntryPoint; -use syntax::{ - SyntaxKind::{ERROR, IDENT}, - T, -}; +use syntax::{SyntaxKind::IDENT, T}; use test_utils::assert_eq_text; use super::*; @@ -101,59 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_inner_macro_rules() { - parse_macro( - r#" -macro_rules! foo { - ($a:ident, $b:ident, $c:tt) => { - - macro_rules! bar { - ($bi:ident) => { - fn $bi() -> u8 {$c} - } - } - - bar!($a); - fn $b() -> u8 {$c} - } -} -"#, - ). - assert_expand_items( - r#"foo!(x,y, 1);"#, - r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#, - ); -} - -#[test] -fn test_expr_after_path_colons() { - assert!(parse_macro( - r#" -macro_rules! m { - ($k:expr) => { - f(K::$k); - } -} -"#, - ) - .expand_statements(r#"m!(C("0"))"#) - .descendants() - .any(|token| token.kind() == ERROR)); -} - -#[test] -fn test_match_is_not_greedy() { - parse_macro( - r#" -macro_rules! foo { - ($($i:ident $(,)*),*) => {}; -} -"#, - ) - .assert_expand_items(r#"foo!(a,b);"#, r#""#); -} - // The following tests are based on real world situations #[test] fn test_vec() { From 5b447701028a74bc47d42045fd5448fe9eaf806f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:24:48 +0300 Subject: [PATCH 07/22] move test --- .../hir_def/src/macro_expansion_tests/mbe.rs | 41 ++++++++ crates/mbe/src/tests/expand.rs | 96 ------------------- 2 files changed, 41 insertions(+), 96 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 7600b16ded75..b028cf25e0d0 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1427,3 +1427,44 @@ macro_rules! foo { "#]], ); } + +// The following tests are based on real world situations +#[test] +fn test_vec() { + check( + r#" +macro_rules! vec { + ($($item:expr),*) => {{ + let mut v = Vec::new(); + $( v.push($item); )* + v + }}; +} +fn main() { + vec!(); + vec![1u32,2]; +} +"#, + expect![[r#" +macro_rules! vec { + ($($item:expr),*) => {{ + let mut v = Vec::new(); + $( v.push($item); )* + v + }}; +} +fn main() { + { + let mut v = Vec::new(); + v + }; + { + let mut v = Vec::new(); + v.push(1u32); + v.push(2); + v + }; +} +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 79f0824b5946..9c0f5273f0c7 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,102 +98,6 @@ fn test_attr_to_token_tree() { ); } -// The following tests are based on real world situations -#[test] -fn test_vec() { - let fixture = parse_macro( - r#" - macro_rules! vec { - ($($item:expr),*) => { - { - let mut v = Vec::new(); - $( - v.push($item); - )* - v - } - }; -} -"#, - ); - fixture - .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#) - .assert_expand_items( - r#"vec![1u32,2];"#, - r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, - ); - - let tree = fixture.expand_expr(r#"vec![1u32,2];"#); - - assert_eq_text!( - &format!("{:#?}", tree), - r#"BLOCK_EXPR@0..45 - STMT_LIST@0..45 - L_CURLY@0..1 "{" - LET_STMT@1..20 - LET_KW@1..4 "let" - IDENT_PAT@4..8 - MUT_KW@4..7 "mut" - NAME@7..8 - IDENT@7..8 "v" - EQ@8..9 "=" - CALL_EXPR@9..19 - PATH_EXPR@9..17 - PATH@9..17 - PATH@9..12 - PATH_SEGMENT@9..12 - NAME_REF@9..12 - IDENT@9..12 "Vec" - COLON2@12..14 "::" - PATH_SEGMENT@14..17 - NAME_REF@14..17 - IDENT@14..17 "new" - ARG_LIST@17..19 - L_PAREN@17..18 "(" - R_PAREN@18..19 ")" - SEMICOLON@19..20 ";" - EXPR_STMT@20..33 - METHOD_CALL_EXPR@20..32 - PATH_EXPR@20..21 - PATH@20..21 - PATH_SEGMENT@20..21 - NAME_REF@20..21 - IDENT@20..21 "v" - DOT@21..22 "." - NAME_REF@22..26 - IDENT@22..26 "push" - ARG_LIST@26..32 - L_PAREN@26..27 "(" - LITERAL@27..31 - INT_NUMBER@27..31 "1u32" - R_PAREN@31..32 ")" - SEMICOLON@32..33 ";" - EXPR_STMT@33..43 - METHOD_CALL_EXPR@33..42 - PATH_EXPR@33..34 - PATH@33..34 - PATH_SEGMENT@33..34 - NAME_REF@33..34 - IDENT@33..34 "v" - DOT@34..35 "." - NAME_REF@35..39 - IDENT@35..39 "push" - ARG_LIST@39..42 - L_PAREN@39..40 "(" - LITERAL@40..41 - INT_NUMBER@40..41 "2" - R_PAREN@41..42 ")" - SEMICOLON@42..43 ";" - PATH_EXPR@43..44 - PATH@43..44 - PATH_SEGMENT@43..44 - NAME_REF@43..44 - IDENT@43..44 "v" - R_CURLY@44..45 "}" -"# - ); -} - #[test] fn test_winapi_struct() { // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 From c986568cbb7712d0135ad276344596c612a53f78 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:26:07 +0300 Subject: [PATCH 08/22] move test --- .../hir_def/src/macro_expansion_tests/mbe.rs | 90 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 36 -------- 2 files changed, 90 insertions(+), 36 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index b028cf25e0d0..cf62b4f5885c 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1468,3 +1468,93 @@ fn main() { "#]], ); } + +#[test] +fn test_winapi_struct() { + // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 + + check( + r#" +macro_rules! STRUCT { + ($(#[$attrs:meta])* struct $name:ident { + $($field:ident: $ftype:ty,)+ + }) => ( + #[repr(C)] #[derive(Copy)] $(#[$attrs])* + pub struct $name { + $(pub $field: $ftype,)+ + } + impl Clone for $name { + #[inline] + fn clone(&self) -> $name { *self } + } + #[cfg(feature = "impl-default")] + impl Default for $name { + #[inline] + fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } + } + ); +} + +// from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs +STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}} + +STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}} +"#, + expect![[r##" +macro_rules! STRUCT { + ($(#[$attrs:meta])* struct $name:ident { + $($field:ident: $ftype:ty,)+ + }) => ( + #[repr(C)] #[derive(Copy)] $(#[$attrs])* + pub struct $name { + $(pub $field: $ftype,)+ + } + impl Clone for $name { + #[inline] + fn clone(&self) -> $name { *self } + } + #[cfg(feature = "impl-default")] + impl Default for $name { + #[inline] + fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } + } + ); +} + +#[repr(C)] +#[derive(Copy)] pub struct D3DVSHADERCAPS2_0 { + pub Caps: u8, +} +impl Clone for D3DVSHADERCAPS2_0 { + #[inline] fn clone(&self ) -> D3DVSHADERCAPS2_0 { + *self + } +} +#[cfg(feature = "impl-default")] impl Default for D3DVSHADERCAPS2_0 { + #[inline] fn default() -> D3DVSHADERCAPS2_0 { + unsafe { + $crate::_core::mem::zeroed() + } + } +} + +#[repr(C)] +#[derive(Copy)] +#[cfg_attr(target_arch = "x86", repr(packed))] pub struct D3DCONTENTPROTECTIONCAPS { + pub Caps: u8, +} +impl Clone for D3DCONTENTPROTECTIONCAPS { + #[inline] fn clone(&self ) -> D3DCONTENTPROTECTIONCAPS { + *self + } +} +#[cfg(feature = "impl-default")] impl Default for D3DCONTENTPROTECTIONCAPS { + #[inline] fn default() -> D3DCONTENTPROTECTIONCAPS { + unsafe { + $crate::_core::mem::zeroed() + } + } +} +"##]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 9c0f5273f0c7..7b6c5a8bddf0 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,42 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_winapi_struct() { - // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 - - parse_macro( - r#" -macro_rules! STRUCT { - ($(#[$attrs:meta])* struct $name:ident { - $($field:ident: $ftype:ty,)+ - }) => ( - #[repr(C)] #[derive(Copy)] $(#[$attrs])* - pub struct $name { - $(pub $field: $ftype,)+ - } - impl Clone for $name { - #[inline] - fn clone(&self) -> $name { *self } - } - #[cfg(feature = "impl-default")] - impl Default for $name { - #[inline] - fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } - } - ); -} -"#, - ). - // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs - assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, - "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}" - ) - .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, - "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}" - ); -} - #[test] fn test_int_base() { parse_macro( From 5ad502dbdb0bb51149ac62ec6227b6a717da05dd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:54:44 +0300 Subject: [PATCH 09/22] move test --- .../hir_def/src/macro_expansion_tests/mbe.rs | 36 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 20 ----------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index cf62b4f5885c..609eac855bc7 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1558,3 +1558,39 @@ impl Clone for D3DCONTENTPROTECTIONCAPS { "##]], ); } + +#[test] +fn test_int_base() { + check( + r#" +macro_rules! int_base { + ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::$Trait for $T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + $Radix.fmt_int(*self as $U, f) + } + } + } +} +int_base!{Binary for isize as usize -> Binary} +"#, + expect![[r##" +macro_rules! int_base { + ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::$Trait for $T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + $Radix.fmt_int(*self as $U, f) + } + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Binary for isize { + fn fmt(&self , f: &mut fmt::Formatter< '_>) -> fmt::Result { + Binary.fmt_int(*self as usize, f) + } +} +"##]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 7b6c5a8bddf0..8c2e656a4cc6 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,26 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_int_base() { - parse_macro( - r#" -macro_rules! int_base { - ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::$Trait for $T { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - $Radix.fmt_int(*self as $U, f) - } - } - } -} -"#, - ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#, - "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" - ); -} - #[test] fn test_generate_pattern_iterators() { // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs From 464fb9f0d45d0b5226936222727ca9b76f5b8424 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:56:41 +0300 Subject: [PATCH 10/22] add directory for regression tests --- .../hir_def/src/macro_expansion_tests/mbe.rs | 168 +---------------- .../macro_expansion_tests/mbe/regression.rs | 175 ++++++++++++++++++ 2 files changed, 176 insertions(+), 167 deletions(-) create mode 100644 crates/hir_def/src/macro_expansion_tests/mbe/regression.rs diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 609eac855bc7..956a6466ccc8 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -4,6 +4,7 @@ mod tt_conversion; mod matching; mod meta_syntax; +mod regression; use expect_test::expect; @@ -1427,170 +1428,3 @@ macro_rules! foo { "#]], ); } - -// The following tests are based on real world situations -#[test] -fn test_vec() { - check( - r#" -macro_rules! vec { - ($($item:expr),*) => {{ - let mut v = Vec::new(); - $( v.push($item); )* - v - }}; -} -fn main() { - vec!(); - vec![1u32,2]; -} -"#, - expect![[r#" -macro_rules! vec { - ($($item:expr),*) => {{ - let mut v = Vec::new(); - $( v.push($item); )* - v - }}; -} -fn main() { - { - let mut v = Vec::new(); - v - }; - { - let mut v = Vec::new(); - v.push(1u32); - v.push(2); - v - }; -} -"#]], - ); -} - -#[test] -fn test_winapi_struct() { - // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 - - check( - r#" -macro_rules! STRUCT { - ($(#[$attrs:meta])* struct $name:ident { - $($field:ident: $ftype:ty,)+ - }) => ( - #[repr(C)] #[derive(Copy)] $(#[$attrs])* - pub struct $name { - $(pub $field: $ftype,)+ - } - impl Clone for $name { - #[inline] - fn clone(&self) -> $name { *self } - } - #[cfg(feature = "impl-default")] - impl Default for $name { - #[inline] - fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } - } - ); -} - -// from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs -STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}} - -STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}} -"#, - expect![[r##" -macro_rules! STRUCT { - ($(#[$attrs:meta])* struct $name:ident { - $($field:ident: $ftype:ty,)+ - }) => ( - #[repr(C)] #[derive(Copy)] $(#[$attrs])* - pub struct $name { - $(pub $field: $ftype,)+ - } - impl Clone for $name { - #[inline] - fn clone(&self) -> $name { *self } - } - #[cfg(feature = "impl-default")] - impl Default for $name { - #[inline] - fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } - } - ); -} - -#[repr(C)] -#[derive(Copy)] pub struct D3DVSHADERCAPS2_0 { - pub Caps: u8, -} -impl Clone for D3DVSHADERCAPS2_0 { - #[inline] fn clone(&self ) -> D3DVSHADERCAPS2_0 { - *self - } -} -#[cfg(feature = "impl-default")] impl Default for D3DVSHADERCAPS2_0 { - #[inline] fn default() -> D3DVSHADERCAPS2_0 { - unsafe { - $crate::_core::mem::zeroed() - } - } -} - -#[repr(C)] -#[derive(Copy)] -#[cfg_attr(target_arch = "x86", repr(packed))] pub struct D3DCONTENTPROTECTIONCAPS { - pub Caps: u8, -} -impl Clone for D3DCONTENTPROTECTIONCAPS { - #[inline] fn clone(&self ) -> D3DCONTENTPROTECTIONCAPS { - *self - } -} -#[cfg(feature = "impl-default")] impl Default for D3DCONTENTPROTECTIONCAPS { - #[inline] fn default() -> D3DCONTENTPROTECTIONCAPS { - unsafe { - $crate::_core::mem::zeroed() - } - } -} -"##]], - ); -} - -#[test] -fn test_int_base() { - check( - r#" -macro_rules! int_base { - ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::$Trait for $T { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - $Radix.fmt_int(*self as $U, f) - } - } - } -} -int_base!{Binary for isize as usize -> Binary} -"#, - expect![[r##" -macro_rules! int_base { - ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::$Trait for $T { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - $Radix.fmt_int(*self as $U, f) - } - } - } -} -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Binary for isize { - fn fmt(&self , f: &mut fmt::Formatter< '_>) -> fmt::Result { - Binary.fmt_int(*self as usize, f) - } -} -"##]], - ); -} diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs new file mode 100644 index 000000000000..0a2c733468cd --- /dev/null +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -0,0 +1,175 @@ +//! Real world regressions and issues, not particularly minimized. +//! +//! While it's OK to just dump large macros here, it's preferable to come up +//! with a minimal example for the program and put a specific test to the parent +//! directory. + +use expect_test::expect; + +use crate::macro_expansion_tests::check; + +#[test] +fn test_vec() { + check( + r#" +macro_rules! vec { + ($($item:expr),*) => {{ + let mut v = Vec::new(); + $( v.push($item); )* + v + }}; +} +fn main() { + vec!(); + vec![1u32,2]; +} +"#, + expect![[r#" +macro_rules! vec { + ($($item:expr),*) => {{ + let mut v = Vec::new(); + $( v.push($item); )* + v + }}; +} +fn main() { + { + let mut v = Vec::new(); + v + }; + { + let mut v = Vec::new(); + v.push(1u32); + v.push(2); + v + }; +} +"#]], + ); +} + +#[test] +fn test_winapi_struct() { + // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 + + check( + r#" +macro_rules! STRUCT { + ($(#[$attrs:meta])* struct $name:ident { + $($field:ident: $ftype:ty,)+ + }) => ( + #[repr(C)] #[derive(Copy)] $(#[$attrs])* + pub struct $name { + $(pub $field: $ftype,)+ + } + impl Clone for $name { + #[inline] + fn clone(&self) -> $name { *self } + } + #[cfg(feature = "impl-default")] + impl Default for $name { + #[inline] + fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } + } + ); +} + +// from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs +STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}} + +STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}} +"#, + expect![[r##" +macro_rules! STRUCT { + ($(#[$attrs:meta])* struct $name:ident { + $($field:ident: $ftype:ty,)+ + }) => ( + #[repr(C)] #[derive(Copy)] $(#[$attrs])* + pub struct $name { + $(pub $field: $ftype,)+ + } + impl Clone for $name { + #[inline] + fn clone(&self) -> $name { *self } + } + #[cfg(feature = "impl-default")] + impl Default for $name { + #[inline] + fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } } + } + ); +} + +#[repr(C)] +#[derive(Copy)] pub struct D3DVSHADERCAPS2_0 { + pub Caps: u8, +} +impl Clone for D3DVSHADERCAPS2_0 { + #[inline] fn clone(&self ) -> D3DVSHADERCAPS2_0 { + *self + } +} +#[cfg(feature = "impl-default")] impl Default for D3DVSHADERCAPS2_0 { + #[inline] fn default() -> D3DVSHADERCAPS2_0 { + unsafe { + $crate::_core::mem::zeroed() + } + } +} + +#[repr(C)] +#[derive(Copy)] +#[cfg_attr(target_arch = "x86", repr(packed))] pub struct D3DCONTENTPROTECTIONCAPS { + pub Caps: u8, +} +impl Clone for D3DCONTENTPROTECTIONCAPS { + #[inline] fn clone(&self ) -> D3DCONTENTPROTECTIONCAPS { + *self + } +} +#[cfg(feature = "impl-default")] impl Default for D3DCONTENTPROTECTIONCAPS { + #[inline] fn default() -> D3DCONTENTPROTECTIONCAPS { + unsafe { + $crate::_core::mem::zeroed() + } + } +} +"##]], + ); +} + +#[test] +fn test_int_base() { + check( + r#" +macro_rules! int_base { + ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::$Trait for $T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + $Radix.fmt_int(*self as $U, f) + } + } + } +} +int_base!{Binary for isize as usize -> Binary} +"#, + expect![[r##" +macro_rules! int_base { + ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::$Trait for $T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + $Radix.fmt_int(*self as $U, f) + } + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Binary for isize { + fn fmt(&self , f: &mut fmt::Formatter< '_>) -> fmt::Result { + Binary.fmt_int(*self as usize, f) + } +} +"##]], + ); +} From 8997d742dc9ed677352d751e3c09b22ec0a9f4b5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:08:49 +0300 Subject: [PATCH 11/22] move tests --- crates/hir_def/src/macro_expansion_tests.rs | 1 + .../macro_expansion_tests/mbe/regression.rs | 202 ++++++++++++++++++ crates/mbe/src/tests/expand.rs | 102 --------- 3 files changed, 203 insertions(+), 102 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index f9527a41358d..eb41a595ce43 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -28,6 +28,7 @@ use crate::{ db::DefDatabase, nameres::ModuleSource, resolver::HasResolver, test_db::TestDB, AsMacroCall, }; +#[track_caller] fn check(ra_fixture: &str, mut expect: Expect) { let db = TestDB::with_files(ra_fixture); let krate = db.crate_graph().iter().next().unwrap(); diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 0a2c733468cd..26fd807e65da 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -173,3 +173,205 @@ macro_rules! int_base { "##]], ); } + +#[test] +fn test_generate_pattern_iterators() { + // From . + check( + r#" +macro_rules! generate_pattern_iterators { + { double ended; with $(#[$common_stability_attribute:meta])*, + $forward_iterator:ident, + $reverse_iterator:ident, $iterty:ty + } => { ok!(); } +} +generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str ); +"#, + expect![[r##" +macro_rules! generate_pattern_iterators { + { double ended; with $(#[$common_stability_attribute:meta])*, + $forward_iterator:ident, + $reverse_iterator:ident, $iterty:ty + } => { ok!(); } +} +ok!(); +"##]], + ); +} + +#[test] +fn test_impl_fn_for_zst() { + // From . + check( + r#" +macro_rules! impl_fn_for_zst { + {$( $( #[$attr: meta] )* + struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = + |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty $body: block; + )+} => {$( + $( #[$attr] )* + struct $Name; + + impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + $body + } + } + + impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call_mut( + &mut self, + ($( $arg, )*): ($( $ArgTy, )*) + ) -> $ReturnTy { + Fn::call(&*self, ($( $arg, )*)) + } + } + + impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name { + type Output = $ReturnTy; + + #[inline] + extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + Fn::call(&self, ($( $arg, )*)) + } + } + )+} +} + +impl_fn_for_zst ! { + #[derive(Clone)] + struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { + c.escape_debug_ext(false) + }; + + #[derive(Clone)] + struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode { + c.escape_unicode() + }; + + #[derive(Clone)] + struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault { + c.escape_default() + }; +} + +"#, + expect![[r##" +macro_rules! impl_fn_for_zst { + {$( $( #[$attr: meta] )* + struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = + |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty $body: block; + )+} => {$( + $( #[$attr] )* + struct $Name; + + impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + $body + } + } + + impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call_mut( + &mut self, + ($( $arg, )*): ($( $ArgTy, )*) + ) -> $ReturnTy { + Fn::call(&*self, ($( $arg, )*)) + } + } + + impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name { + type Output = $ReturnTy; + + #[inline] + extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + Fn::call(&self, ($( $arg, )*)) + } + } + )+} +} + +#[derive(Clone)] struct CharEscapeDebugContinue; +impl Fn<(char, )> for CharEscapeDebugContinue { + #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDebug { { + c.escape_debug_ext(false ) + } + } +} +impl FnMut<(char, )> for CharEscapeDebugContinue { + #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDebug { + Fn::call(&*self , (c, )) + } +} +impl FnOnce<(char, )> for CharEscapeDebugContinue { + type Output = char::EscapeDebug; + #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDebug { + Fn::call(&self , (c, )) + } +} +#[derive(Clone)] struct CharEscapeUnicode; +impl Fn<(char, )> for CharEscapeUnicode { + #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeUnicode { { + c.escape_unicode() + } + } +} +impl FnMut<(char, )> for CharEscapeUnicode { + #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeUnicode { + Fn::call(&*self , (c, )) + } +} +impl FnOnce<(char, )> for CharEscapeUnicode { + type Output = char::EscapeUnicode; + #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeUnicode { + Fn::call(&self , (c, )) + } +} +#[derive(Clone)] struct CharEscapeDefault; +impl Fn<(char, )> for CharEscapeDefault { + #[inline] extern "rust-call"fn call(&self , (c, ): (char, )) -> char::EscapeDefault { { + c.escape_default() + } + } +} +impl FnMut<(char, )> for CharEscapeDefault { + #[inline] extern "rust-call"fn call_mut(&mut self , (c, ): (char, )) -> char::EscapeDefault { + Fn::call(&*self , (c, )) + } +} +impl FnOnce<(char, )> for CharEscapeDefault { + type Output = char::EscapeDefault; + #[inline] extern "rust-call"fn call_once(self , (c, ): (char, )) -> char::EscapeDefault { + Fn::call(&self , (c, )) + } +} + +"##]], + ); +} + +#[test] +fn test_impl_nonzero_fmt() { + // From . + check( + r#" +macro_rules! impl_nonzero_fmt { + ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { ok!(); } +} +impl_nonzero_fmt! { + #[stable(feature= "nonzero",since="1.28.0")] + (Debug, Display, Binary, Octal, LowerHex, UpperHex) for NonZeroU8 +} +"#, + expect![[r##" +macro_rules! impl_nonzero_fmt { + ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { ok!(); } +} +ok!(); +"##]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 8c2e656a4cc6..6152e01bc879 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,108 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_generate_pattern_iterators() { - // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs - parse_macro( - r#" -macro_rules! generate_pattern_iterators { - { double ended; with $(#[$common_stability_attribute:meta])*, - $forward_iterator:ident, - $reverse_iterator:ident, $iterty:ty - } => { - fn foo(){} - } -} -"#, - ).assert_expand_items( - r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#, - "fn foo () {}", - ); -} - -#[test] -fn test_impl_fn_for_zst() { - // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs - parse_macro( - r#" -macro_rules! impl_fn_for_zst { - { $( $( #[$attr: meta] )* - struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = - |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty -$body: block; )+ - } => { - $( - $( #[$attr] )* - struct $Name; - - impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name { - #[inline] - extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { - $body - } - } - - impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name { - #[inline] - extern "rust-call" fn call_mut( - &mut self, - ($( $arg, )*): ($( $ArgTy, )*) - ) -> $ReturnTy { - Fn::call(&*self, ($( $arg, )*)) - } - } - - impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name { - type Output = $ReturnTy; - - #[inline] - extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { - Fn::call(&self, ($( $arg, )*)) - } - } - )+ -} - } -"#, - ).assert_expand_items(r#" -impl_fn_for_zst ! { - # [ derive ( Clone ) ] - struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug { - c . escape_debug_ext ( false ) - } ; - - # [ derive ( Clone ) ] - struct CharEscapeUnicode impl Fn = | c : char | -> char :: EscapeUnicode { - c . escape_unicode ( ) - } ; - # [ derive ( Clone ) ] - struct CharEscapeDefault impl Fn = | c : char | -> char :: EscapeDefault { - c . escape_default ( ) - } ; - } -"#, - "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}" - ); -} - -#[test] -fn test_impl_nonzero_fmt() { - // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12 - parse_macro( - r#" - macro_rules! impl_nonzero_fmt { - ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { - fn foo () {} - } - } -"#, - ).assert_expand_items( - r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#, - "fn foo () {}", - ); -} - #[test] fn test_cfg_if_items() { // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 From e55797f59d47153651661588e9ff09ffb75c6e67 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:21:47 +0300 Subject: [PATCH 12/22] move tests --- crates/hir_def/src/macro_expansion_tests.rs | 4 +- .../macro_expansion_tests/mbe/regression.rs | 102 ++++++++++++++++++ crates/mbe/src/tests/expand.rs | 63 ----------- 3 files changed, 105 insertions(+), 64 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index eb41a595ce43..7d9d7f39d050 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -144,7 +144,9 @@ fn pretty_print_macro_expansion(expn: SyntaxNode) -> String { (T![>], _) if curr_kind.is_keyword() => " ", (T![->], _) | (_, T![->]) => " ", (T![&&], _) | (_, T![&&]) => " ", - (T![,] | T![:], _) => " ", + (T![,], _) => " ", + (T![:], IDENT | T!['(']) => " ", + (T![:], _) if curr_kind.is_keyword() => " ", (T![fn], T!['(']) => "", (T![']'], _) if curr_kind.is_keyword() => " ", (T![']'], T![#]) => "\n", diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 26fd807e65da..ac09c23cd3e0 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -375,3 +375,105 @@ ok!(); "##]], ); } + +#[test] +fn test_cfg_if_items() { + // From . + check( + r#" +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} +__cfg_if_items! { + (rustdoc,); + ( () ( + #[ cfg(any(target_os = "redox", unix))] + #[ stable(feature = "rust1", since = "1.0.0")] + pub use sys::ext as unix; + + #[cfg(windows)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use sys::ext as windows; + + #[cfg(any(target_os = "linux", target_os = "l4re"))] + pub mod linux; + )), +} +"#, + expect![[r#" +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} +__cfg_if_items! { + (rustdoc, ); +} +"#]], + ); +} + +#[test] +fn test_cfg_if_main() { + // From . + check( + r#" +macro_rules! cfg_if { + ($(if #[cfg($($meta:meta),*)] { $($it:item)* } )else* else { $($it2:item)* }) + => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + }; + + // Internal macro to Apply a cfg attribute to a list of items + (@__apply $m:meta, $($it:item)*) => { $(#[$m] $it)* }; +} + +cfg_if! { + if #[cfg(target_env = "msvc")] { + // no extra unwinder support needed + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + // no unwinder on the system! + } else { + mod libunwind; + pub use libunwind::*; + } +} + +cfg_if! { + @__apply cfg(all(not(any(not(any(target_os = "solaris", target_os = "illumos")))))), +} +"#, + expect![[r##" +macro_rules! cfg_if { + ($(if #[cfg($($meta:meta),*)] { $($it:item)* } )else* else { $($it2:item)* }) + => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + }; + + // Internal macro to Apply a cfg attribute to a list of items + (@__apply $m:meta, $($it:item)*) => { $(#[$m] $it)* }; +} + +__cfg_if_items! { + (); + ((target_env = "msvc")()), ((all(target_arch = "wasm32", not(target_os = "emscripten")))()), (()(mod libunwind; + pub use libunwind::*; + )), +} + + +"##]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 6152e01bc879..1287b3ea9b96 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,69 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_cfg_if_items() { - // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 - parse_macro( - r#" - macro_rules! __cfg_if_items { - (($($not:meta,)*) ; ) => {}; - (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } - } - } -"#, - ).assert_expand_items( - r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#, - "__cfg_if_items ! {(rustdoc ,) ;}", - ); -} - -#[test] -fn test_cfg_if_main() { - // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9 - parse_macro( - r#" - macro_rules! cfg_if { - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - __cfg_if_items! { - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } - }; - - // Internal macro to Apply a cfg attribute to a list of items - (@__apply $m:meta, $($it:item)*) => { - $(#[$m] $it)* - }; - } -"#, - ).assert_expand_items(r#" -cfg_if ! { - if # [ cfg ( target_env = "msvc" ) ] { - // no extra unwinder support needed - } else if # [ cfg ( all ( target_arch = "wasm32" , not ( target_os = "emscripten" ) ) ) ] { - // no unwinder on the system! - } else { - mod libunwind ; - pub use libunwind :: * ; - } - } -"#, - "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}" - ).assert_expand_items( - r#" -cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } -"#, - "", - ); -} - #[test] fn test_proptest_arbitrary() { // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 From 6253213a6e4c9a1d0059d5ed9834e1eb2808d927 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:23:52 +0300 Subject: [PATCH 13/22] move test --- .../macro_expansion_tests/mbe/regression.rs | 56 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 28 ---------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index ac09c23cd3e0..9762570412c3 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -477,3 +477,59 @@ __cfg_if_items! { "##]], ); } + +#[test] +fn test_proptest_arbitrary() { + // From . + check( + r#" +macro_rules! arbitrary { + ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; + $args: ident => $logic: expr) => { + impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ { + type Parameters = $params; + type Strategy = $strat; + fn arbitrary_with($args: Self::Parameters) -> Self::Strategy { + $logic + } + } + }; +} + +arbitrary!( + [A:Arbitrary] + Vec , + VecStrategy, + RangedParams1; + args => { + let product_unpack![range, a] = args; + vec(any_with::(a), range) + } +); +"#, + expect![[r#" +macro_rules! arbitrary { + ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; + $args: ident => $logic: expr) => { + impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ { + type Parameters = $params; + type Strategy = $strat; + fn arbitrary_with($args: Self::Parameters) -> Self::Strategy { + $logic + } + } + }; +} + +impl $crate::arbitrary::Arbitrary for Vec { + type Parameters = RangedParams1; + type Strategy = VecStrategy; + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { { + let product_unpack![range, a] = args; + vec(any_with::(a), range) + } + } +} +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 1287b3ea9b96..300467306d6b 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,34 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_proptest_arbitrary() { - // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 - parse_macro( - r#" -macro_rules! arbitrary { - ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; - $args: ident => $logic: expr) => { - impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ { - type Parameters = $params; - type Strategy = $strat; - fn arbitrary_with($args: Self::Parameters) -> Self::Strategy { - $logic - } - } - }; - -}"#, - ).assert_expand_items(r#"arbitrary ! ( [ A : Arbitrary ] - Vec < A > , - VecStrategy < A :: Strategy > , - RangedParams1 < A :: Parameters > ; - args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) } - ) ;"#, - "impl $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}" - ); -} - #[test] fn test_old_ridl() { // This is from winapi 2.8, which do not have a link from github From af76db3c3663e517a3e8e2c05bee494453bf9877 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:26:47 +0300 Subject: [PATCH 14/22] move tests --- .../macro_expansion_tests/mbe/regression.rs | 107 ++++++++++++++++++ crates/mbe/src/tests/expand.rs | 66 ----------- 2 files changed, 107 insertions(+), 66 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 9762570412c3..527395992b1e 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -533,3 +533,110 @@ impl $crate::arbitrary::Arbitrary for Vec { "#]], ); } + +#[test] +fn test_old_ridl() { + // This is from winapi 2.8, which do not have a link from github. + check( + r#" +#[macro_export] +macro_rules! RIDL { + (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) + {$( + fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty + ),+} + ) => { + impl $interface { + $(pub unsafe fn $method(&mut self) -> $rtr { + ((*self.lpVtbl).$method)(self $(,$p)*) + })+ + } + }; +} + +RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { + fn GetDataSize(&mut self) -> UINT +}} +"#, + expect![[r##" +#[macro_export] +macro_rules! RIDL { + (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) + {$( + fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty + ),+} + ) => { + impl $interface { + $(pub unsafe fn $method(&mut self) -> $rtr { + ((*self.lpVtbl).$method)(self $(,$p)*) + })+ + } + }; +} + +impl ID3D11Asynchronous { + pub unsafe fn GetDataSize(&mut self ) -> UINT { + ((*self .lpVtbl).GetDataSize)(self ) + } +} +"##]], + ); +} + +#[test] +fn test_quick_error() { + check( + r#" +macro_rules! quick_error { + (SORT [enum $name:ident $( #[$meta:meta] )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [ ] + queue [ ] + ) => { + quick_error!(ENUMINITION [enum $name $( #[$meta] )*] + body [] + queue [$( + $( #[$imeta] )* + => + $iitem: $imode [$( $ivar: $ityp ),*] + )*] + ); + }; +} +quick_error ! ( + SORT + [enum Wrapped #[derive(Debug)]] + items [ + => One: UNIT [] {} + => Two: TUPLE [s :String] {display ("two: {}" , s) from ()} ] + buf [ ] + queue [ ] +); + +"#, + expect![[r##" +macro_rules! quick_error { + (SORT [enum $name:ident $( #[$meta:meta] )*] + items [$($( #[$imeta:meta] )* + => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] + {$( $ifuncs:tt )*} )* ] + buf [ ] + queue [ ] + ) => { + quick_error!(ENUMINITION [enum $name $( #[$meta] )*] + body [] + queue [$( + $( #[$imeta] )* + => + $iitem: $imode [$( $ivar: $ityp ),*] + )*] + ); + }; +} +quick_error!(ENUMINITION[enum Wrapped#[derive(Debug)]]body[]queue[ = > One: UNIT[] = > Two: TUPLE[s: String]]); + +"##]], + ) +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 300467306d6b..c3c753cf558b 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,72 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_old_ridl() { - // This is from winapi 2.8, which do not have a link from github - // - let expanded = parse_macro( - r#" -#[macro_export] -macro_rules! RIDL { - (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) - {$( - fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty - ),+} - ) => { - impl $interface { - $(pub unsafe fn $method(&mut self) -> $rtr { - ((*self.lpVtbl).$method)(self $(,$p)*) - })+ - } - }; -}"#, - ).expand_tt(r#" - RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { - fn GetDataSize(&mut self) -> UINT - }}"#); - - assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}"); -} - -#[test] -fn test_quick_error() { - let expanded = parse_macro( - r#" -macro_rules! quick_error { - - (SORT [enum $name:ident $( #[$meta:meta] )*] - items [$($( #[$imeta:meta] )* - => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*] - {$( $ifuncs:tt )*} )* ] - buf [ ] - queue [ ] - ) => { - quick_error!(ENUMINITION [enum $name $( #[$meta] )*] - body [] - queue [$( - $( #[$imeta] )* - => - $iitem: $imode [$( $ivar: $ityp ),*] - )*] - ); -}; - -} -"#, - ) - .expand_tt( - r#" -quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ - => One : UNIT [] {} - => Two : TUPLE [s :String] {display ("two: {}" , s) from ()} - ] buf [] queue []) ; -"#, - ); - - assert_eq!(expanded.to_string(), "quick_error ! (ENUMINITION [enum Wrapped # [derive (Debug)]] body [] queue [=> One : UNIT [] => Two : TUPLE [s : String]]) ;"); -} - #[test] fn test_empty_repeat_vars_in_empty_repeat_vars() { parse_macro( From be73cc8f8354c797fd6159b0d5d61fd56ecdc4a7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:28:04 +0300 Subject: [PATCH 15/22] move test --- .../macro_expansion_tests/mbe/regression.rs | 88 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 48 ---------- 2 files changed, 88 insertions(+), 48 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 527395992b1e..5f650d458a43 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -640,3 +640,91 @@ quick_error!(ENUMINITION[enum Wrapped#[derive(Debug)]]body[]queue[ = > One: UNIT "##]], ) } + +#[test] +fn test_empty_repeat_vars_in_empty_repeat_vars() { + check( + r#" +macro_rules! delegate_impl { + ([$self_type:ident, $self_wrap:ty, $self_map:ident] + pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { + + $( + @escape [type $assoc_name_ext:ident] + )* + $( + @section type + $( + $(#[$_assoc_attr:meta])* + type $assoc_name:ident $(: $assoc_bound:ty)*; + )+ + )* + $( + @section self + $( + $(#[$_method_attr:meta])* + fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty; + )+ + )* + $( + @section nodelegate + $($tail:tt)* + )* + }) => { + impl<> $name for $self_wrap where $self_type: $name { + $( + $( + fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret { + $self_map!(self).$method_name($($marg),*) + } + )* + )* + } + } +} +delegate_impl ! { + [G, &'a mut G, deref] pub trait Data: GraphBase {@section type type NodeWeight;} +} +"#, + expect![[r##" +macro_rules! delegate_impl { + ([$self_type:ident, $self_wrap:ty, $self_map:ident] + pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { + + $( + @escape [type $assoc_name_ext:ident] + )* + $( + @section type + $( + $(#[$_assoc_attr:meta])* + type $assoc_name:ident $(: $assoc_bound:ty)*; + )+ + )* + $( + @section self + $( + $(#[$_method_attr:meta])* + fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty; + )+ + )* + $( + @section nodelegate + $($tail:tt)* + )* + }) => { + impl<> $name for $self_wrap where $self_type: $name { + $( + $( + fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret { + $self_map!(self).$method_name($($marg),*) + } + )* + )* + } + } +} +impl <> Data for & 'amut G where G: Data {} +"##]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index c3c753cf558b..6c2e91668ef1 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,54 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn test_empty_repeat_vars_in_empty_repeat_vars() { - parse_macro( - r#" -macro_rules! delegate_impl { - ([$self_type:ident, $self_wrap:ty, $self_map:ident] - pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { - - $( - @escape [type $assoc_name_ext:ident] - )* - $( - @section type - $( - $(#[$_assoc_attr:meta])* - type $assoc_name:ident $(: $assoc_bound:ty)*; - )+ - )* - $( - @section self - $( - $(#[$_method_attr:meta])* - fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty; - )+ - )* - $( - @section nodelegate - $($tail:tt)* - )* - }) => { - impl<> $name for $self_wrap where $self_type: $name { - $( - $( - fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret { - $self_map!(self).$method_name($($marg),*) - } - )* - )* - } - } -} -"#, - ).assert_expand_items( - r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, - "impl <> Data for & \'a mut G where G : Data {}", - ); -} - #[test] fn expr_interpolation() { let expanded = parse_macro( From 42fd71e6c8884397cfcb9d514a0a7f1aacf929ca Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:40:13 +0300 Subject: [PATCH 16/22] move tests --- .../hir_def/src/macro_expansion_tests/mbe.rs | 18 +++ .../macro_expansion_tests/mbe/regression.rs | 151 ++++++++++++++++++ crates/mbe/src/tests/expand.rs | 80 ---------- 3 files changed, 169 insertions(+), 80 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index 956a6466ccc8..1da0110fe261 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -1428,3 +1428,21 @@ macro_rules! foo { "#]], ); } + +#[test] +fn expr_interpolation() { + check( + r#" +macro_rules! m { ($expr:expr) => { map($expr) } } +fn f() { + let _ = m!(x + foo); +} +"#, + expect![[r#" +macro_rules! m { ($expr:expr) => { map($expr) } } +fn f() { + let _ = map(x+foo); +} +"#]], + ) +} diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 5f650d458a43..5e23ca88fa9d 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -728,3 +728,154 @@ impl <> Data for & 'amut G where G: Data {} "##]], ); } + +#[test] +fn test_issue_2520() { + check( + r#" +macro_rules! my_macro { + { + ( $( + $( [] $sname:ident : $stype:ty )? + $( [$expr:expr] $nname:ident : $ntype:ty )? + ),* ) + } => {ok!( + Test { + $( + $( $sname, )? + )* + } + );}; +} + +my_macro! { + ([] p1: u32, [|_| S0K0] s: S0K0, [] k0: i32) +} + "#, + expect![[r#" +macro_rules! my_macro { + { + ( $( + $( [] $sname:ident : $stype:ty )? + $( [$expr:expr] $nname:ident : $ntype:ty )? + ),* ) + } => {ok!( + Test { + $( + $( $sname, )? + )* + } + );}; +} + +ok!(Test { + p1, k0, +} +); + "#]], + ); +} + +#[test] +fn test_repeat_bad_var() { + // FIXME: the second rule of the macro should be removed and an error about + // `$( $c )+` raised + check( + r#" +macro_rules! foo { + ($( $b:ident )+) => { ok!($( $c )+); }; + ($( $b:ident )+) => { ok!($( $b )+); } +} + +foo!(b0 b1); +"#, + expect![[r#" +macro_rules! foo { + ($( $b:ident )+) => { ok!($( $c )+); }; + ($( $b:ident )+) => { ok!($( $b )+); } +} + +ok!(b0 b1); +"#]], + ); +} + +#[test] +fn test_issue_3861() { + // This is should (and does) produce a parse error. It used to infinite loop + // instead. + check( + r#" +macro_rules! rgb_color { + ($p:expr, $t:ty) => { + pub fn new() { + let _ = 0 as $t << $p; + } + }; +} +// +tree +errors +rgb_color!(8 + 8, u32); +"#, + expect![[r#" +macro_rules! rgb_color { + ($p:expr, $t:ty) => { + pub fn new() { + let _ = 0 as $t << $p; + } + }; +} +/* parse error: expected type */ +/* parse error: expected R_ANGLE */ +/* parse error: expected COMMA */ +/* parse error: expected R_ANGLE */ +/* parse error: expected SEMICOLON */ +pub fn new() { + let _ = 0as u32<<8+8; +} +// MACRO_ITEMS@0..29 +// FN@0..29 +// VISIBILITY@0..3 +// PUB_KW@0..3 "pub" +// FN_KW@3..5 "fn" +// NAME@5..8 +// IDENT@5..8 "new" +// PARAM_LIST@8..10 +// L_PAREN@8..9 "(" +// R_PAREN@9..10 ")" +// BLOCK_EXPR@10..29 +// STMT_LIST@10..29 +// L_CURLY@10..11 "{" +// LET_STMT@11..24 +// LET_KW@11..14 "let" +// WILDCARD_PAT@14..15 +// UNDERSCORE@14..15 "_" +// EQ@15..16 "=" +// CAST_EXPR@16..24 +// LITERAL@16..17 +// INT_NUMBER@16..17 "0" +// AS_KW@17..19 "as" +// PATH_TYPE@19..24 +// PATH@19..24 +// PATH_SEGMENT@19..24 +// NAME_REF@19..22 +// IDENT@19..22 "u32" +// GENERIC_ARG_LIST@22..24 +// L_ANGLE@22..23 "<" +// TYPE_ARG@23..24 +// PATH_TYPE@23..24 +// PATH@23..24 +// PATH_SEGMENT@23..24 +// L_ANGLE@23..24 "<" +// EXPR_STMT@24..28 +// BIN_EXPR@24..27 +// LITERAL@24..25 +// INT_NUMBER@24..25 "8" +// PLUS@25..26 "+" +// LITERAL@26..27 +// INT_NUMBER@26..27 "8" +// SEMICOLON@27..28 ";" +// R_CURLY@28..29 "}" + +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 6c2e91668ef1..ffb24709f223 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -98,86 +98,6 @@ fn test_attr_to_token_tree() { ); } -#[test] -fn expr_interpolation() { - let expanded = parse_macro( - r#" - macro_rules! id { - ($expr:expr) => { - map($expr) - } - } - "#, - ) - .expand_expr("id!(x + foo);"); - - assert_eq!(expanded.to_string(), "map(x+foo)"); -} - -#[test] -fn test_issue_2520() { - let macro_fixture = parse_macro( - r#" - macro_rules! my_macro { - { - ( $( - $( [] $sname:ident : $stype:ty )? - $( [$expr:expr] $nname:ident : $ntype:ty )? - ),* ) - } => { - Test { - $( - $( $sname, )? - )* - } - }; - } - "#, - ); - - macro_fixture.assert_expand_items( - r#"my_macro ! { - ([] p1 : u32 , [|_| S0K0] s : S0K0 , [] k0 : i32) - }"#, - "Test {p1 , k0 ,}", - ); -} - -#[test] -fn test_issue_3861() { - let macro_fixture = parse_macro( - r#" - macro_rules! rgb_color { - ($p:expr, $t: ty) => { - pub fn new() { - let _ = 0 as $t << $p; - } - }; - } - "#, - ); - - macro_fixture.expand_items(r#"rgb_color!(8 + 8, u32);"#); -} - -#[test] -fn test_repeat_bad_var() { - // FIXME: the second rule of the macro should be removed and an error about - // `$( $c )+` raised - parse_macro( - r#" - macro_rules! foo { - ($( $b:ident )+) => { - $( $c )+ - }; - ($( $b:ident )+) => { - $( $b )+ - } - } - "#, - ) - .assert_expand_items("foo!(b0 b1);", "b0 b1"); -} #[test] fn test_no_space_after_semi_colon() { From dce41e5a03d5d85cfddcc3a91a7e1c82f6c6119b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 14:58:25 +0300 Subject: [PATCH 17/22] move tests --- .../macro_expansion_tests/mbe/meta_syntax.rs | 61 ++++++++++++++ .../macro_expansion_tests/mbe/regression.rs | 21 +++++ crates/mbe/src/tests.rs | 9 --- crates/mbe/src/tests/expand.rs | 79 ------------------- 4 files changed, 82 insertions(+), 88 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/meta_syntax.rs b/crates/hir_def/src/macro_expansion_tests/mbe/meta_syntax.rs index d434c8824492..dd5effa3683a 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/meta_syntax.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/meta_syntax.rs @@ -77,3 +77,64 @@ macro_rules! f3 { ($i:_) => () } "#]], ) } + +#[test] +fn test_rustc_issue_57597() { + // + check( + r#" +macro_rules! m0 { ($($($i:ident)?)+) => {}; } +macro_rules! m1 { ($($($i:ident)?)*) => {}; } +macro_rules! m2 { ($($($i:ident)?)?) => {}; } +macro_rules! m3 { ($($($($i:ident)?)?)?) => {}; } +macro_rules! m4 { ($($($($i:ident)*)?)?) => {}; } +macro_rules! m5 { ($($($($i:ident)?)*)?) => {}; } +macro_rules! m6 { ($($($($i:ident)?)?)*) => {}; } +macro_rules! m7 { ($($($($i:ident)*)*)?) => {}; } +macro_rules! m8 { ($($($($i:ident)?)*)*) => {}; } +macro_rules! m9 { ($($($($i:ident)?)*)+) => {}; } +macro_rules! mA { ($($($($i:ident)+)?)*) => {}; } +macro_rules! mB { ($($($($i:ident)+)*)?) => {}; } + +m0!(); +m1!(); +m2!(); +m3!(); +m4!(); +m5!(); +m6!(); +m7!(); +m8!(); +m9!(); +mA!(); +mB!(); + "#, + expect![[r#" +macro_rules! m0 { ($($($i:ident)?)+) => {}; } +macro_rules! m1 { ($($($i:ident)?)*) => {}; } +macro_rules! m2 { ($($($i:ident)?)?) => {}; } +macro_rules! m3 { ($($($($i:ident)?)?)?) => {}; } +macro_rules! m4 { ($($($($i:ident)*)?)?) => {}; } +macro_rules! m5 { ($($($($i:ident)?)*)?) => {}; } +macro_rules! m6 { ($($($($i:ident)?)?)*) => {}; } +macro_rules! m7 { ($($($($i:ident)*)*)?) => {}; } +macro_rules! m8 { ($($($($i:ident)?)*)*) => {}; } +macro_rules! m9 { ($($($($i:ident)?)*)+) => {}; } +macro_rules! mA { ($($($($i:ident)+)?)*) => {}; } +macro_rules! mB { ($($($($i:ident)+)*)?) => {}; } + +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ +/* error: invalid macro definition: empty token tree in repetition */ + "#]], + ); +} diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs index 5e23ca88fa9d..563fe5058850 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/regression.rs @@ -879,3 +879,24 @@ pub fn new() { "#]], ); } + +#[test] +fn test_no_space_after_semi_colon() { + check( + r#" +macro_rules! with_std { + ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) +} + +with_std! {mod m;mod f;} +"#, + expect![[r##" +macro_rules! with_std { + ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) +} + +#[cfg(feature = "std")] mod m; +#[cfg(feature = "std")] mod f; +"##]], + ) +} diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 64d80baa3ed1..78e24a37e6f9 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs @@ -141,15 +141,6 @@ pub(crate) fn parse_macro(ra_fixture: &str) -> MacroFixture { MacroFixture { rules } } -pub(crate) fn parse_macro_error(ra_fixture: &str) -> ParseError { - let definition_tt = parse_macro_rules_to_tt(ra_fixture); - - match MacroRules::parse(&definition_tt) { - Ok(_) => panic!("Expect error"), - Err(err) => err, - } -} - pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree { let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); let tt = syntax_node_to_token_tree(source_file.syntax()).0; diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index ffb24709f223..8a23a0be532c 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -1,6 +1,5 @@ use ::parser::ParserEntryPoint; use syntax::{SyntaxKind::IDENT, T}; -use test_utils::assert_eq_text; use super::*; @@ -98,84 +97,6 @@ fn test_attr_to_token_tree() { ); } - -#[test] -fn test_no_space_after_semi_colon() { - let expanded = parse_macro( - r#" - macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) } - "#, - ) - .expand_items(r#"with_std! {mod m;mod f;}"#); - - let dump = format!("{:#?}", expanded); - assert_eq_text!( - r###"MACRO_ITEMS@0..52 - MODULE@0..26 - ATTR@0..21 - POUND@0..1 "#" - L_BRACK@1..2 "[" - META@2..20 - PATH@2..5 - PATH_SEGMENT@2..5 - NAME_REF@2..5 - IDENT@2..5 "cfg" - TOKEN_TREE@5..20 - L_PAREN@5..6 "(" - IDENT@6..13 "feature" - EQ@13..14 "=" - STRING@14..19 "\"std\"" - R_PAREN@19..20 ")" - R_BRACK@20..21 "]" - MOD_KW@21..24 "mod" - NAME@24..25 - IDENT@24..25 "m" - SEMICOLON@25..26 ";" - MODULE@26..52 - ATTR@26..47 - POUND@26..27 "#" - L_BRACK@27..28 "[" - META@28..46 - PATH@28..31 - PATH_SEGMENT@28..31 - NAME_REF@28..31 - IDENT@28..31 "cfg" - TOKEN_TREE@31..46 - L_PAREN@31..32 "(" - IDENT@32..39 "feature" - EQ@39..40 "=" - STRING@40..45 "\"std\"" - R_PAREN@45..46 ")" - R_BRACK@46..47 "]" - MOD_KW@47..50 "mod" - NAME@50..51 - IDENT@50..51 "f" - SEMICOLON@51..52 ";""###, - dump.trim() - ); -} - -// https://github.com/rust-lang/rust/blob/master/src/test/ui/issues/issue-57597.rs -#[test] -fn test_rustc_issue_57597() { - fn test_error(fixture: &str) { - assert_eq!(parse_macro_error(fixture), ParseError::RepetitionEmptyTokenTree); - } - - test_error("macro_rules! foo { ($($($i:ident)?)+) => {}; }"); - test_error("macro_rules! foo { ($($($i:ident)?)*) => {}; }"); - test_error("macro_rules! foo { ($($($i:ident)?)?) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)?)?)?) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)*)?)?) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)?)*)?) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)?)?)*) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)*)*)?) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)?)*)*) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)?)*)+) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)+)?)*) => {}; }"); - test_error("macro_rules! foo { ($($($($i:ident)+)*)?) => {}; }"); -} - #[test] fn test_expand_bad_literal() { parse_macro( From 0f849a7a35e21d0b17eeed702ac91d0273dc8848 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 15:06:41 +0300 Subject: [PATCH 18/22] move test --- .../src/macro_expansion_tests/mbe/matching.rs | 27 +++++++++++++++++++ crates/mbe/src/tests/expand.rs | 23 ---------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/matching.rs b/crates/hir_def/src/macro_expansion_tests/mbe/matching.rs index 5bdabfc598ba..9fb6d96b7254 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe/matching.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe/matching.rs @@ -23,3 +23,30 @@ literal!(); "#]], ) } + +#[test] +fn test_expand_bad_literal() { + check( + r#" +macro_rules! m { ($i:literal) => {}; } +m!(&k"); +"#, + expect![[r#" +macro_rules! m { ($i:literal) => {}; } +/* error: Failed to lower macro args to token tree */"#]], + ); +} + +#[test] +fn test_empty_comments() { + check( + r#" +macro_rules! m{ ($fmt:expr) => (); } +m!(/**/); +"#, + expect![[r#" +macro_rules! m{ ($fmt:expr) => (); } +/* error: expected Expr */ +"#]], + ); +} diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 8a23a0be532c..3380e01fbc7a 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs @@ -96,26 +96,3 @@ fn test_attr_to_token_tree() { Some(tt::DelimiterKind::Bracket) ); } - -#[test] -fn test_expand_bad_literal() { - parse_macro( - r#" - macro_rules! foo { ($i:literal) => {}; } - "#, - ) - .assert_expand_err(r#"foo!(&k");"#, &ExpandError::BindingError("".into())); -} - -#[test] -fn test_empty_comments() { - parse_macro( - r#" - macro_rules! one_arg_macro { ($fmt:expr) => (); } - "#, - ) - .assert_expand_err( - r#"one_arg_macro!(/**/)"#, - &ExpandError::BindingError("expected Expr".into()), - ); -} From bfc5d8529a678ffb0207246a4bc9cf72814f6213 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 15:11:33 +0300 Subject: [PATCH 19/22] drop obsolete tests --- crates/mbe/src/tests.rs | 205 +-------------------------------- crates/mbe/src/tests/expand.rs | 98 ---------------- 2 files changed, 2 insertions(+), 301 deletions(-) delete mode 100644 crates/mbe/src/tests/expand.rs diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 78e24a37e6f9..f4d7e6059593 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs @@ -1,210 +1,9 @@ -mod expand; +use std::iter; -use std::{fmt::Write, iter}; - -use syntax::{ast, AstNode, NodeOrToken, SyntaxNode, WalkEvent}; -use test_utils::assert_eq_text; - -use crate::ParserEntryPoint; +use syntax::{ast, AstNode}; use super::*; -pub(crate) struct MacroFixture { - rules: MacroRules, -} - -pub(crate) struct MacroFixture2 { - rules: MacroDef, -} - -macro_rules! impl_fixture { - ($name:ident) => { - impl $name { - pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree { - self.try_expand_tt(invocation).unwrap() - } - - fn try_expand_tt(&self, invocation: &str) -> Result { - let source_file = ast::SourceFile::parse(invocation).tree(); - let macro_invocation = - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); - - let (invocation_tt, _) = - syntax_node_to_token_tree(macro_invocation.token_tree().unwrap().syntax()); - - self.rules.expand(&invocation_tt).result() - } - - #[allow(unused)] - fn assert_expand_err(&self, invocation: &str, err: &ExpandError) { - assert_eq!(self.try_expand_tt(invocation).as_ref(), Err(err)); - } - - #[allow(unused)] - fn expand_items(&self, invocation: &str) -> SyntaxNode { - let expanded = self.expand_tt(invocation); - token_tree_to_syntax_node(&expanded, ParserEntryPoint::Items) - .unwrap() - .0 - .syntax_node() - } - - #[allow(unused)] - fn expand_statements(&self, invocation: &str) -> SyntaxNode { - let expanded = self.expand_tt(invocation); - token_tree_to_syntax_node(&expanded, ParserEntryPoint::Statements) - .unwrap() - .0 - .syntax_node() - } - - #[allow(unused)] - fn expand_expr(&self, invocation: &str) -> SyntaxNode { - let expanded = self.expand_tt(invocation); - token_tree_to_syntax_node(&expanded, ParserEntryPoint::Expr) - .unwrap() - .0 - .syntax_node() - } - - #[allow(unused)] - fn assert_expand_tt(&self, invocation: &str, expected: &str) { - let expansion = self.expand_tt(invocation); - assert_eq!(expansion.to_string(), expected); - } - - #[allow(unused)] - fn assert_expand(&self, invocation: &str, expected: &str) { - let expansion = self.expand_tt(invocation); - let actual = format!("{:?}", expansion); - test_utils::assert_eq_text!(&expected.trim(), &actual.trim()); - } - - #[allow(unused)] - fn assert_expand_items(&self, invocation: &str, expected: &str) -> &$name { - self.assert_expansion(ParserEntryPoint::Items, invocation, expected); - self - } - - #[allow(unused)] - fn assert_expand_statements(&self, invocation: &str, expected: &str) -> &$name { - self.assert_expansion(ParserEntryPoint::Statements, invocation, expected); - self - } - - fn assert_expansion(&self, kind: ParserEntryPoint, invocation: &str, expected: &str) { - let expanded = self.expand_tt(invocation); - assert_eq!(expanded.to_string(), expected); - - let expected = expected.replace("$crate", "C_C__C"); - - // wrap the given text to a macro call - let expected = { - let wrapped = format!("wrap_macro!( {} )", expected); - let wrapped = ast::SourceFile::parse(&wrapped); - let wrapped = wrapped - .tree() - .syntax() - .descendants() - .find_map(ast::TokenTree::cast) - .unwrap(); - let mut wrapped = syntax_node_to_token_tree(wrapped.syntax()).0; - wrapped.delimiter = None; - wrapped - }; - - let expanded_tree = - token_tree_to_syntax_node(&expanded, kind).unwrap().0.syntax_node(); - let expanded_tree = debug_dump_ignore_spaces(&expanded_tree).trim().to_string(); - - let expected_tree = - token_tree_to_syntax_node(&expected, kind).unwrap().0.syntax_node(); - let expected_tree = debug_dump_ignore_spaces(&expected_tree).trim().to_string(); - - let expected_tree = expected_tree.replace("C_C__C", "$crate"); - assert_eq!( - expanded_tree, expected_tree, - "\nleft:\n{}\nright:\n{}", - expanded_tree, expected_tree, - ); - } - } - }; -} - -impl_fixture!(MacroFixture); -impl_fixture!(MacroFixture2); - -pub(crate) fn parse_macro(ra_fixture: &str) -> MacroFixture { - let definition_tt = parse_macro_rules_to_tt(ra_fixture); - let rules = MacroRules::parse(&definition_tt).unwrap(); - MacroFixture { rules } -} - -pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree { - let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); - let tt = syntax_node_to_token_tree(source_file.syntax()).0; - - let parsed = parse_to_token_tree(ra_fixture).unwrap().0; - assert_eq!(tt, parsed); - - parsed -} - -fn parse_macro_rules_to_tt(ra_fixture: &str) -> tt::Subtree { - let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); - let macro_definition = - source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); - - let (definition_tt, _) = - syntax_node_to_token_tree(macro_definition.token_tree().unwrap().syntax()); - - let parsed = parse_to_token_tree( - &ra_fixture[macro_definition.token_tree().unwrap().syntax().text_range()], - ) - .unwrap() - .0; - assert_eq!(definition_tt, parsed); - - definition_tt -} - -fn debug_dump_ignore_spaces(node: &syntax::SyntaxNode) -> String { - let mut level = 0; - let mut buf = String::new(); - macro_rules! indent { - () => { - for _ in 0..level { - buf.push_str(" "); - } - }; - } - - for event in node.preorder_with_tokens() { - match event { - WalkEvent::Enter(element) => { - match element { - NodeOrToken::Node(node) => { - indent!(); - writeln!(buf, "{:?}", node.kind()).unwrap(); - } - NodeOrToken::Token(token) => match token.kind() { - syntax::SyntaxKind::WHITESPACE => {} - _ => { - indent!(); - writeln!(buf, "{:?}", token.kind()).unwrap(); - } - }, - } - level += 1; - } - WalkEvent::Leave(_) => level -= 1, - } - } - - buf -} - #[test] fn test_node_to_tt_censor() { use syntax::ast::{HasAttrs, HasModuleItem}; diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs deleted file mode 100644 index 3380e01fbc7a..000000000000 --- a/crates/mbe/src/tests/expand.rs +++ /dev/null @@ -1,98 +0,0 @@ -use ::parser::ParserEntryPoint; -use syntax::{SyntaxKind::IDENT, T}; - -use super::*; - -// Good first issue (although a slightly challenging one): -// -// * Pick a random test from here -// https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt -// * Port the test to rust and add it to this module -// * Make it pass :-) - -#[test] -fn test_token_id_shift() { - let expansion = parse_macro( - r#" -macro_rules! foobar { - ($e:ident) => { foo bar $e } -} -"#, - ) - .expand_tt("foobar!(baz);"); - - fn get_id(t: &tt::TokenTree) -> Option { - if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t { - return Some(ident.id.0); - } - None - } - - assert_eq!(expansion.token_trees.len(), 3); - // {($e:ident) => { foo bar $e }} - // 012345 67 8 9 T 12 - assert_eq!(get_id(&expansion.token_trees[0]), Some(9)); - assert_eq!(get_id(&expansion.token_trees[1]), Some(10)); - - // The input args of macro call include parentheses: - // (baz) - // So baz should be 12+1+1 - assert_eq!(get_id(&expansion.token_trees[2]), Some(14)); -} - -#[test] -fn test_token_map() { - let expanded = parse_macro( - r#" -macro_rules! foobar { - ($e:ident) => { fn $e() {} } -} -"#, - ) - .expand_tt("foobar!(baz);"); - - let (node, token_map) = token_tree_to_syntax_node(&expanded, ParserEntryPoint::Items).unwrap(); - let content = node.syntax_node().to_string(); - - let get_text = |id, kind| -> String { - content[token_map.first_range_by_token(id, kind).unwrap()].to_string() - }; - - assert_eq!(expanded.token_trees.len(), 4); - // {($e:ident) => { fn $e() {} }} - // 012345 67 8 9 T12 3 - - assert_eq!(get_text(tt::TokenId(9), IDENT), "fn"); - assert_eq!(get_text(tt::TokenId(12), T!['(']), "("); - assert_eq!(get_text(tt::TokenId(13), T!['{']), "{"); -} - -fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree { - if let tt::TokenTree::Subtree(subtree) = tt { - return subtree; - } - unreachable!("It is not a subtree"); -} - -fn to_punct(tt: &tt::TokenTree) -> &tt::Punct { - if let tt::TokenTree::Leaf(tt::Leaf::Punct(lit)) = tt { - return lit; - } - unreachable!("It is not a Punct"); -} - -#[test] -fn test_attr_to_token_tree() { - let expansion = parse_to_token_tree_by_syntax( - r#" - #[derive(Copy)] - struct Foo; - "#, - ); - - assert_eq!(to_punct(&expansion.token_trees[0]).char, '#'); - assert_eq!( - to_subtree(&expansion.token_trees[1]).delimiter_kind(), - Some(tt::DelimiterKind::Bracket) - ); -} From 6a3fc849214b9f56e0649656cea722f9eba4627f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 15:17:53 +0300 Subject: [PATCH 20/22] internal: move builtin macro tests to macro expansion suite --- crates/hir_def/src/macro_expansion_tests.rs | 1 + .../src/macro_expansion_tests/builtin.rs | 121 ++++++++++++++++++ crates/hir_expand/src/builtin_macro.rs | 76 ----------- 3 files changed, 122 insertions(+), 76 deletions(-) create mode 100644 crates/hir_def/src/macro_expansion_tests/builtin.rs diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index 7d9d7f39d050..9c91ea8a7abd 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -10,6 +10,7 @@ //! and harder to understand. mod mbe; +mod builtin; use std::{iter, ops::Range}; diff --git a/crates/hir_def/src/macro_expansion_tests/builtin.rs b/crates/hir_def/src/macro_expansion_tests/builtin.rs new file mode 100644 index 000000000000..c2b900b9df39 --- /dev/null +++ b/crates/hir_def/src/macro_expansion_tests/builtin.rs @@ -0,0 +1,121 @@ +//! Tests for builtin macros (see `builtin_macro.rs` in `hir_expand`). + +use expect_test::expect; + +use crate::macro_expansion_tests::check; + +#[test] +fn test_column_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! column {() => {}} + +fn main() { column!(); } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! column {() => {}} + +fn main() { 0; } +"##]], + ); +} + +#[test] +fn test_line_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! line {() => {}} + +fn main() { line!() } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! line {() => {}} + +fn main() { 0 } +"##]], + ); +} + +#[test] +fn test_stringify_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! stringify {() => {}} + +fn main() { + stringify!( + a + b + c + ); +} +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! stringify {() => {}} + +fn main() { + "a b c"; +} +"##]], + ); +} + +#[test] +fn test_env_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! env {() => {}} + +fn main() { env!("TEST_ENV_VAR"); } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! env {() => {}} + +fn main() { "__RA_UNIMPLEMENTED__"; } +"##]], + ); +} + +#[test] +fn test_option_env_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! option_env {() => {}} + +fn main() { option_env!("TEST_ENV_VAR"); } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! option_env {() => {}} + +fn main() { std::option::Option::None:: < &str>; } +"##]], + ); +} + +#[test] +fn test_file_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! file {() => {}} + +fn main() { file!(); } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! file {() => {}} + +fn main() { ""; } +"##]], + ); +} diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index a4ddafbf7af4..55dc665c5d78 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs @@ -669,82 +669,6 @@ mod tests { expect.assert_eq(&expansion); } - #[test] - fn test_column_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! column {() => {}} - column!() - "#, - expect![["0"]], - ); - } - - #[test] - fn test_line_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! line {() => {}} - line!() - "#, - expect![["0"]], - ); - } - - #[test] - fn test_stringify_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! stringify {() => {}} - stringify!( - a - b - c - ) - "#, - expect![["\"a b c\""]], - ); - } - - #[test] - fn test_env_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! env {() => {}} - env!("TEST_ENV_VAR") - "#, - expect![["\"__RA_UNIMPLEMENTED__\""]], - ); - } - - #[test] - fn test_option_env_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! option_env {() => {}} - option_env!("TEST_ENV_VAR") - "#, - expect![["std::option::Option::None:: < &str>"]], - ); - } - - #[test] - fn test_file_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! file {() => {}} - file!() - "#, - expect![[r#""""#]], - ); - } - #[test] fn test_assert_expand() { check_expansion( From 5f8b708aca74cb7316d2f8dfd81feae087473907 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 15:28:24 +0300 Subject: [PATCH 21/22] move tests --- crates/hir_def/src/macro_expansion_tests.rs | 6 +- .../src/macro_expansion_tests/builtin.rs | 151 ++++++++++++++++++ crates/hir_expand/src/builtin_macro.rs | 82 ---------- 3 files changed, 155 insertions(+), 84 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index 9c91ea8a7abd..c317dc27a583 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -46,17 +46,19 @@ fn check(ra_fixture: &str, mut expect: Expect) { let mut expansions = Vec::new(); for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) { let macro_call = InFile::new(source.file_id, ¯o_call); + let mut error = None; let macro_call_id = macro_call .as_call_id_with_errors( &db, krate, |path| resolver.resolve_path_as_macro(&db, &path), - &mut |err| panic!("{}", err), + &mut |err| error = Some(err), ) .unwrap() .unwrap(); let macro_file = MacroFile { macro_call_id }; - let expansion_result = db.parse_macro_expansion(macro_file); + let mut expansion_result = db.parse_macro_expansion(macro_file); + expansion_result.err = expansion_result.err.or(error); expansions.push((macro_call.value.clone(), expansion_result)); } diff --git a/crates/hir_def/src/macro_expansion_tests/builtin.rs b/crates/hir_def/src/macro_expansion_tests/builtin.rs index c2b900b9df39..1b25caa0ff1b 100644 --- a/crates/hir_def/src/macro_expansion_tests/builtin.rs +++ b/crates/hir_def/src/macro_expansion_tests/builtin.rs @@ -119,3 +119,154 @@ fn main() { ""; } "##]], ); } + +#[test] +fn test_assert_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + assert!(true, "{} {:?}", arg1(a, b, c), arg2); +} +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + { + if !true { + $crate::panic!("{} {:?}", arg1(a, b, c), arg2); + } + }; +} +"##]], + ); +} + +#[test] +fn test_compile_error_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); + ($msg:expr,) => ({ /* compiler built-in */ }) +} + +// This expands to nothing (since it's in item position), but emits an error. +compile_error!("error!"); +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); + ($msg:expr,) => ({ /* compiler built-in */ }) +} + +/* error: error! */ +"##]], + ); +} + +#[test] +fn test_format_args_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + format_args!("{} {:?}", arg1(a, b, c), arg2); +} +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + unsafe { + std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a, b, c)), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(arg2), std::fmt::Display::fmt), ]) + }; +} +"##]], + ); +} + +#[test] +fn test_format_args_expand_with_comma_exprs() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + format_args!("{} {:?}", a::(), b); +} +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + unsafe { + std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::()), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(b), std::fmt::Display::fmt), ]) + }; +} +"##]], + ); +} + +#[test] +fn test_format_args_expand_with_broken_member_access() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + let _ = + // +errors + format_args!("{} {:?}", a.); +} +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) +} + +fn main() { + let _ = + /* parse error: expected field name or number */ +unsafe { + std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a.), std::fmt::Display::fmt), ]) + }; +} +"##]], + ); +} diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 55dc665c5d78..f988ffff09ee 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs @@ -669,88 +669,6 @@ mod tests { expect.assert_eq(&expansion); } - #[test] - fn test_assert_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! assert { - ($cond:expr) => ({ /* compiler built-in */ }); - ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ }) - } - assert!(true, "{} {:?}", arg1(a, b, c), arg2); - "#, - expect![[r#"{if!true{$crate::panic!("{} {:?}",arg1(a,b,c),arg2);}}"#]], - ); - } - - #[test] - fn test_compile_error_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! compile_error { - ($msg:expr) => ({ /* compiler built-in */ }); - ($msg:expr,) => ({ /* compiler built-in */ }) - } - compile_error!("error!"); - "#, - // This expands to nothing (since it's in item position), but emits an error. - expect![[""]], - ); - } - - #[test] - fn test_format_args_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) - } - format_args!("{} {:?}", arg1(a, b, c), arg2); - "#, - expect![[ - r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])}"# - ]], - ); - } - - #[test] - fn test_format_args_expand_with_comma_exprs() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) - } - format_args!("{} {:?}", a::(), b); - "#, - expect![[ - r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])}"# - ]], - ); - } - - #[test] - fn test_format_args_expand_with_broken_member_access() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) - } - format_args!("{} {:?}", a.); - "#, - expect![[ - r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a.),std::fmt::Display::fmt),])}"# - ]], - ); - } - #[test] fn test_include_bytes_expand() { check_expansion( From e5acf650d0ec90058fa0ab378e1ae5dae903c98e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Oct 2021 15:30:54 +0300 Subject: [PATCH 22/22] move tests --- .../src/macro_expansion_tests/builtin.rs | 60 ++++++++ crates/hir_expand/src/builtin_macro.rs | 143 ------------------ 2 files changed, 60 insertions(+), 143 deletions(-) diff --git a/crates/hir_def/src/macro_expansion_tests/builtin.rs b/crates/hir_def/src/macro_expansion_tests/builtin.rs index 1b25caa0ff1b..6982116522c6 100644 --- a/crates/hir_def/src/macro_expansion_tests/builtin.rs +++ b/crates/hir_def/src/macro_expansion_tests/builtin.rs @@ -270,3 +270,63 @@ unsafe { "##]], ); } + +#[test] +fn test_include_bytes_expand() { + check( + r#" +#[rustc_builtin_macro] +macro_rules! include_bytes { + ($file:expr) => {{ /* compiler built-in */ }}; + ($file:expr,) => {{ /* compiler built-in */ }}; +} + +fn main() { include_bytes("foo"); } +"#, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! include_bytes { + ($file:expr) => {{ /* compiler built-in */ }}; + ($file:expr,) => {{ /* compiler built-in */ }}; +} + +fn main() { include_bytes("foo"); } +"##]], + ); +} + +#[test] +fn test_concat_expand() { + check( + r##" +#[rustc_builtin_macro] +macro_rules! concat {} + +fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false); } +"##, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! concat {} + +fn main() { "foor0bar\nfalse"; } +"##]], + ); +} + +#[test] +fn test_concat_idents_expand() { + check( + r##" +#[rustc_builtin_macro] +macro_rules! concat_idents {} + +fn main() { concat_idents!(foo, bar); } +"##, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! concat_idents {} + +fn main() { foobar; } +"##]], + ); +} diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index f988ffff09ee..4b801eb2a154 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs @@ -565,146 +565,3 @@ fn option_env_expand( ExpandResult::ok(Some(ExpandedEager::new(expanded))) } - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use base_db::{fixture::WithFixture, SourceDatabase}; - use expect_test::{expect, Expect}; - use syntax::ast::HasName; - - use crate::{ - name::AsName, test_db::TestDB, AstNode, EagerCallInfo, ExpandTo, MacroCallId, - MacroCallKind, MacroCallLoc, - }; - - use super::*; - - fn expand_builtin_macro(ra_fixture: &str) -> String { - let (db, file_id) = TestDB::with_single_file(ra_fixture); - let parsed = db.parse(file_id); - let mut macro_rules: Vec<_> = - parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); - let mut macro_calls: Vec<_> = - parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); - - let ast_id_map = db.ast_id_map(file_id.into()); - - assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); - assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); - let macro_rules = ast::Macro::from(macro_rules.pop().unwrap()); - let macro_call = macro_calls.pop().unwrap(); - - let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); - let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules)); - - let krate = CrateId(0); - let file_id = match expander { - Either::Left(expander) => { - // the first one should be a macro_rules - let def = MacroDefId { - krate: CrateId(0), - kind: MacroDefKind::BuiltIn(expander, ast_id), - local_inner: false, - }; - - let loc = MacroCallLoc { - def, - krate, - eager: None, - kind: MacroCallKind::FnLike { - ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)), - expand_to: ExpandTo::Expr, - }, - }; - - let id: MacroCallId = db.intern_macro(loc); - id.as_file() - } - Either::Right(expander) => { - // the first one should be a macro_rules - let def = MacroDefId { - krate, - kind: MacroDefKind::BuiltInEager(expander, ast_id), - local_inner: false, - }; - - let args = macro_call.token_tree().unwrap(); - let parsed_args = mbe::syntax_node_to_token_tree(args.syntax()).0; - let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); - - let arg_id = db.intern_macro(MacroCallLoc { - def, - krate, - eager: Some(EagerCallInfo { - arg_or_expansion: Arc::new(parsed_args.clone()), - included_file: None, - }), - kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr }, - }); - - let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); - let expand_to = crate::ExpandTo::from_call_site(¯o_call); - let loc = MacroCallLoc { - def, - krate, - eager: Some(EagerCallInfo { - arg_or_expansion: Arc::new(expanded.subtree), - included_file: expanded.included_file, - }), - kind: MacroCallKind::FnLike { ast_id: call_id, expand_to }, - }; - - let id: MacroCallId = db.intern_macro(loc); - id.as_file() - } - }; - - db.parse_or_expand(file_id).unwrap().to_string() - } - - fn check_expansion(ra_fixture: &str, expect: Expect) { - let expansion = expand_builtin_macro(ra_fixture); - expect.assert_eq(&expansion); - } - - #[test] - fn test_include_bytes_expand() { - check_expansion( - r#" - #[rustc_builtin_macro] - macro_rules! include_bytes { - ($file:expr) => {{ /* compiler built-in */ }}; - ($file:expr,) => {{ /* compiler built-in */ }}; - } - include_bytes("foo"); - "#, - expect![[r#"b"""#]], - ); - } - - #[test] - fn test_concat_expand() { - check_expansion( - r##" - #[rustc_builtin_macro] - macro_rules! concat {} - concat!("foo", "r", 0, r#"bar"#, "\n", false); - "##, - expect![[r#""foor0bar\nfalse""#]], - ); - } - - #[test] - fn test_concat_idents_expand() { - check_expansion( - r##" - #[rustc_builtin_macro] - macro_rules! concat_idents {} - concat_idents!(foo, bar); - "##, - expect![[r#"foobar"#]], - ); - } -}