]> git.lizzy.rs Git - rust.git/commitdiff
Fix `concat!` with integer literals
authorJonas Schievink <jonasschievink@gmail.com>
Tue, 8 Dec 2020 19:06:41 +0000 (20:06 +0100)
committerJonas Schievink <jonasschievink@gmail.com>
Tue, 8 Dec 2020 19:06:41 +0000 (20:06 +0100)
crates/hir_expand/src/builtin_macro.rs

index 44a5556b67f46641a3bbced8a6ec9a9a1d1d7b42..79b970850481d8223f952026cea55b402fd9cf60 100644 (file)
@@ -287,23 +287,34 @@ fn concat_expand(
     _arg_id: EagerMacroId,
     tt: &tt::Subtree,
 ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
+    let mut err = None;
     let mut text = String::new();
     for (i, t) in tt.token_trees.iter().enumerate() {
         match t {
             tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
-                text += &match unquote_str(&it) {
-                    Some(s) => s,
-                    None => {
-                        return ExpandResult::only_err(mbe::ExpandError::ConversionError);
-                    }
-                };
+                // concat works with string and char literals, so remove any quotes.
+                // It also works with integer, float and boolean literals, so just use the rest
+                // as-is.
+
+                text += it
+                    .text
+                    .trim_start_matches(|c| match c {
+                        'r' | '#' | '\'' | '"' => true,
+                        _ => false,
+                    })
+                    .trim_end_matches(|c| match c {
+                        '#' | '\'' | '"' => true,
+                        _ => false,
+                    });
             }
             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
-            _ => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken),
+            _ => {
+                err.get_or_insert(mbe::ExpandError::UnexpectedToken);
+            }
         }
     }
 
-    ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
+    ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
 }
 
 fn relative_file(
@@ -686,4 +697,19 @@ macro_rules! include_bytes {
 
         assert_eq!(expanded, r#"b"""#);
     }
+
+    #[test]
+    fn test_concat_expand() {
+        let expanded = expand_builtin_macro(
+            r##"
+            #[rustc_builtin_macro]
+            macro_rules! concat {}
+            concat!("foo", 0, r#"bar"#);
+            "##,
+        );
+
+        assert_eq!(expanded, r#""foo0bar""#);
+
+        // FIXME: `true`/`false` literals don't work.
+    }
 }