aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_expand/src/builtin_macro.rs42
1 files changed, 34 insertions, 8 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 44a5556b6..79b970850 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -287,23 +287,34 @@ fn concat_expand(
287 _arg_id: EagerMacroId, 287 _arg_id: EagerMacroId,
288 tt: &tt::Subtree, 288 tt: &tt::Subtree,
289) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { 289) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
290 let mut err = None;
290 let mut text = String::new(); 291 let mut text = String::new();
291 for (i, t) in tt.token_trees.iter().enumerate() { 292 for (i, t) in tt.token_trees.iter().enumerate() {
292 match t { 293 match t {
293 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { 294 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
294 text += &match unquote_str(&it) { 295 // concat works with string and char literals, so remove any quotes.
295 Some(s) => s, 296 // It also works with integer, float and boolean literals, so just use the rest
296 None => { 297 // as-is.
297 return ExpandResult::only_err(mbe::ExpandError::ConversionError); 298
298 } 299 text += it
299 }; 300 .text
301 .trim_start_matches(|c| match c {
302 'r' | '#' | '\'' | '"' => true,
303 _ => false,
304 })
305 .trim_end_matches(|c| match c {
306 '#' | '\'' | '"' => true,
307 _ => false,
308 });
300 } 309 }
301 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), 310 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
302 _ => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken), 311 _ => {
312 err.get_or_insert(mbe::ExpandError::UnexpectedToken);
313 }
303 } 314 }
304 } 315 }
305 316
306 ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) 317 ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
307} 318}
308 319
309fn relative_file( 320fn relative_file(
@@ -686,4 +697,19 @@ mod tests {
686 697
687 assert_eq!(expanded, r#"b"""#); 698 assert_eq!(expanded, r#"b"""#);
688 } 699 }
700
701 #[test]
702 fn test_concat_expand() {
703 let expanded = expand_builtin_macro(
704 r##"
705 #[rustc_builtin_macro]
706 macro_rules! concat {}
707 concat!("foo", 0, r#"bar"#);
708 "##,
709 );
710
711 assert_eq!(expanded, r#""foo0bar""#);
712
713 // FIXME: `true`/`false` literals don't work.
714 }
689} 715}