Merge #7059
7059: Special case $_ in meta var instead of treat it as ident in mbe r=lnicola a=edwin0cheng In #6929, we treat '_' as an ident but rustc is only allow it in some special places (e.g. meta var in mbe , type, pat etc). This PR rollback that and we only make '$_' works in meta var matching. Fixes #7056 Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
99ec2f623d
@ -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;
|
||||
|
@ -313,7 +313,7 @@ fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.push(if k.is_punct() && k != UNDERSCORE {
|
||||
result.push(if k.is_punct() {
|
||||
assert_eq!(range.len(), TextSize::of('.'));
|
||||
let delim = match k {
|
||||
T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])),
|
||||
@ -378,7 +378,6 @@ macro_rules! make_leaf {
|
||||
let leaf: tt::Leaf = match k {
|
||||
T![true] | T![false] => make_leaf!(Ident),
|
||||
IDENT => make_leaf!(Ident),
|
||||
UNDERSCORE => make_leaf!(Ident),
|
||||
k if k.is_keyword() => make_leaf!(Ident),
|
||||
k if k.is_literal() => make_leaf!(Literal),
|
||||
LIFETIME_IDENT => {
|
||||
|
@ -1019,6 +1019,42 @@ macro_rules! foo {
|
||||
.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(
|
||||
|
Loading…
Reference in New Issue
Block a user