Special case underscore in mbe meta op

This commit is contained in:
Edwin Cheng 2020-12-28 18:51:43 +08:00
parent b33453f844
commit b5c29af02a
2 changed files with 45 additions and 2 deletions

View File

@ -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;

View File

@ -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(