Skip to content

Commit ca352e0

Browse files
fix: negative nums in concat! expansion
1 parent 37acea8 commit ca352e0

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

Diff for: crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -456,13 +456,13 @@ fn test_concat_expand() {
456456
#[rustc_builtin_macro]
457457
macro_rules! concat {}
458458
459-
fn main() { concat!("fo", "o", 0, r#""bar""#, "\n", false, '"', '\0'); }
459+
fn main() { concat!("fo", "o", 0, r#""bar""#, "\n", false, '"', -4, '\0'); }
460460
"##,
461461
expect![[r##"
462462
#[rustc_builtin_macro]
463463
macro_rules! concat {}
464464
465-
fn main() { "foo0\"bar\"\nfalse\"\u{0}"; }
465+
fn main() { "foo0\"bar\"\nfalse\"-4\u{0}"; }
466466
"##]],
467467
);
468468
}

Diff for: crates/hir-expand/src/builtin/fn_macro.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,10 @@ fn concat_expand(
456456
Some(_) => (),
457457
None => span = Some(s),
458458
};
459-
for (i, mut t) in tt.iter().enumerate() {
459+
460+
let mut i = 0;
461+
let mut iter = tt.iter();
462+
while let Some(mut t) = iter.next() {
460463
// FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
461464
// to ensure the right parsing order, so skip the parentheses here. Ideally we'd
462465
// implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
@@ -508,10 +511,40 @@ fn concat_expand(
508511
record_span(id.span);
509512
}
510513
TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
514+
// handle negative numbers
515+
TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 0 && punct.char == '-' => {
516+
let t = match iter.next() {
517+
Some(t) => t,
518+
None => {
519+
err.get_or_insert(ExpandError::other(
520+
call_site,
521+
"unexpected end of input after '-'",
522+
));
523+
break;
524+
}
525+
};
526+
527+
match t {
528+
TtElement::Leaf(tt::Leaf::Literal(it))
529+
if matches!(it.kind, tt::LitKind::Integer | tt::LitKind::Float) =>
530+
{
531+
format_to!(text, "-{}", it.symbol.as_str());
532+
record_span(punct.span.cover(it.span));
533+
}
534+
_ => {
535+
err.get_or_insert(ExpandError::other(
536+
call_site,
537+
"expected number after '-'",
538+
));
539+
break;
540+
}
541+
}
542+
}
511543
_ => {
512544
err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
513545
}
514546
}
547+
i += 1;
515548
}
516549
let span = span.unwrap_or_else(|| tt.top_subtree().delimiter.open);
517550
ExpandResult { value: quote!(span =>#text), err }

0 commit comments

Comments
 (0)