]> git.lizzy.rs Git - rust.git/commitdiff
Special case underscore in mbe meta op
authorEdwin Cheng <edwin0cheng@gmail.com>
Mon, 28 Dec 2020 10:51:43 +0000 (18:51 +0800)
committerEdwin Cheng <edwin0cheng@gmail.com>
Mon, 28 Dec 2020 10:51:43 +0000 (18:51 +0800)
crates/mbe/src/parser.rs
crates/mbe/src/tests.rs

index c3fdd40404894e5009e4fd33c70fb39a41060482..d681905f5728f1b093c0ca88763edc2edfb1353c 100644 (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;
index 6cd0ed205395249eba780d633231a65f23fe61f4..9958a33a08d0fffd01802a8bf5e4fda2dacaf6ab 100644 (file)
@@ -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(