6768: Fix `concat!` with integer literals r=jonas-schievink a=jonas-schievink

Addresses https://github.com/rust-analyzer/rust-analyzer/issues/6747#issuecomment-740778402

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2020-12-08 19:07:59 +00:00 committed by GitHub
commit 0e2b1b7b8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View 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 @@ mod tests {
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.
}
}