Skip to content

Commit b569bbb

Browse files
committed
Auto merge of rust-lang#12942 - lowr:fix/concat-with-char, r=Veykril
fix: make `concat!` work with char Fixes rust-lang#12921 - I avoided making `unquote_str()` take char literals as well because it's depended on by another function `parse_string()` that's only supposed to take strings. - Even with this patch, we don't output `\0` as `\u{0}` which rust-lang#12921 pointed out ~~, but we're not actually responsible for serializing it but rowan is~~. They are functionally equivalent and I don't think it'd cause any confusion, but we *could* try escaping them before serialization (for reference, `rustc -Zunpretty=expanded`, which `cargo expand` uses under the hood, [makes use of `str::escape_default()`](https://github.com/rust-lang/rust/blob/3830ecaa8db798d2727cbdfa4ddf314ff938f268/compiler/rustc_ast/src/util/literal.rs#L161).
2 parents 634cfe3 + 4d5873e commit b569bbb

File tree

3 files changed

+16
-6
lines changed

3 files changed

+16
-6
lines changed

crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,13 @@ fn test_concat_expand() {
295295
#[rustc_builtin_macro]
296296
macro_rules! concat {}
297297
298-
fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false); }
298+
fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false, '"', '\0'); }
299299
"##,
300300
expect![[r##"
301301
#[rustc_builtin_macro]
302302
macro_rules! concat {}
303303
304-
fn main() { "foor0bar\nfalse"; }
304+
fn main() { "foor0bar\nfalse\"\u{0}"; }
305305
"##]],
306306
);
307307
}

crates/hir-expand/src/builtin_fn_macro.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
357357
token.value().map(|it| it.into_owned())
358358
}
359359

360+
fn unquote_char(lit: &tt::Literal) -> Option<char> {
361+
let lit = ast::make::tokens::literal(&lit.to_string());
362+
let token = ast::Char::cast(lit)?;
363+
token.value()
364+
}
365+
360366
fn unquote_byte_string(lit: &tt::Literal) -> Option<Vec<u8>> {
361367
let lit = ast::make::tokens::literal(&lit.to_string());
362368
let token = ast::ByteString::cast(lit)?;
@@ -408,8 +414,12 @@ fn concat_expand(
408414
// concat works with string and char literals, so remove any quotes.
409415
// It also works with integer, float and boolean literals, so just use the rest
410416
// as-is.
411-
let component = unquote_str(it).unwrap_or_else(|| it.text.to_string());
412-
text.push_str(&component);
417+
if let Some(c) = unquote_char(it) {
418+
text.push(c);
419+
} else {
420+
let component = unquote_str(it).unwrap_or_else(|| it.text.to_string());
421+
text.push_str(&component);
422+
}
413423
}
414424
// handle boolean literals
415425
tt::TokenTree::Leaf(tt::Leaf::Ident(id))

crates/hir-expand/src/quote.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ impl_to_to_tokentrees! {
196196
tt::Literal => self { self };
197197
tt::Ident => self { self };
198198
tt::Punct => self { self };
199-
&str => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}};
200-
String => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}}
199+
&str => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}};
200+
String => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}}
201201
}
202202

203203
#[cfg(test)]

0 commit comments

Comments
 (0)