diff options
author | Jonas Schievink <[email protected]> | 2020-12-08 19:06:41 +0000 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-12-08 19:06:41 +0000 |
commit | bb28aef9184c98450b81ec7faca99a5c327619ea (patch) | |
tree | a1e40210c2644646553bdbc2bc821c06c56da9c4 | |
parent | 70fa57f8d30c80927465de9a1b8501d7a2ee4925 (diff) |
Fix `concat!` with integer literals
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 42 |
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 | ||
309 | fn relative_file( | 320 | fn 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 | } |