From b5c29af02a88d0354ae1cbdabb41d481132f476e Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Mon, 28 Dec 2020 18:51:43 +0800 Subject: Special case underscore in mbe meta op --- crates/mbe/src/parser.rs | 11 +++++++++-- crates/mbe/src/tests.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs index c3fdd4040..d681905f5 100644 --- a/crates/mbe/src/parser.rs +++ b/crates/mbe/src/parser.rs @@ -101,8 +101,15 @@ fn next_op<'a>( Op::Repeat { subtree, separator, kind } } tt::TokenTree::Leaf(leaf) => match leaf { - tt::Leaf::Punct(_) => { - return Err(ExpandError::UnexpectedToken); + tt::Leaf::Punct(punct) => { + static UNDERSCORE: SmolStr = SmolStr::new_inline("_"); + + if punct.char != '_' { + return Err(ExpandError::UnexpectedToken); + } + let name = &UNDERSCORE; + let kind = eat_fragment_kind(src, mode)?; + Op::Var { name, kind } } tt::Leaf::Ident(ident) => { let name = &ident.text; diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 6cd0ed205..9958a33a0 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs @@ -1019,6 +1019,42 @@ fn test_underscore() { .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_vertical_bar_with_pat() { parse_macro( -- cgit v1.2.3