Skip to content

Commit 2b2d9d8

Browse files
authored
Merge pull request #20745 from Oblarg/fix-negative-int-literals-in-macro-by-example
Fix negative integer literals in const generics in declarative macro context
2 parents 062ac7a + b8852fd commit 2b2d9d8

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

crates/ide/src/hover/tests.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4796,6 +4796,48 @@ fn main() {
47964796
);
47974797
}
47984798

4799+
#[test]
4800+
fn const_generic_negative_literal_macro_expansion() {
4801+
// Test that negative literals work correctly in const generics
4802+
// when used through macro expansion. This ensures the transcriber
4803+
// doesn't wrap negative literals in parentheses, which would create
4804+
// invalid syntax like Foo::<(-1)> instead of Foo::<-1>.
4805+
check(
4806+
r#"
4807+
struct Foo<const I: i16> {
4808+
pub value: i16,
4809+
}
4810+
4811+
impl<const I: i16> Foo<I> {
4812+
pub fn new(value: i16) -> Self {
4813+
Self { value }
4814+
}
4815+
}
4816+
4817+
macro_rules! create_foo {
4818+
($val:expr) => {
4819+
Foo::<$val>::new($val)
4820+
};
4821+
}
4822+
4823+
fn main() {
4824+
let v$0alue = create_foo!(-1);
4825+
}
4826+
"#,
4827+
expect![[r#"
4828+
*value*
4829+
4830+
```rust
4831+
let value: Foo<-1>
4832+
```
4833+
4834+
---
4835+
4836+
size = 2, align = 2, no Drop
4837+
"#]],
4838+
);
4839+
}
4840+
47994841
#[test]
48004842
fn hover_self_param_shows_type() {
48014843
check(

crates/mbe/src/expander/transcriber.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,19 @@ fn expand_var(
401401
let sub = sub.strip_invisible();
402402
let mut span = id;
403403
marker(&mut span);
404-
let wrap_in_parens = !matches!(sub.flat_tokens(), [tt::TokenTree::Leaf(_)])
404+
405+
// Check if this is a simple negative literal (MINUS + LITERAL)
406+
// that should not be wrapped in parentheses
407+
let is_negative_literal = matches!(
408+
sub.flat_tokens(),
409+
[
410+
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '-', .. })),
411+
tt::TokenTree::Leaf(tt::Leaf::Literal(_))
412+
]
413+
);
414+
415+
let wrap_in_parens = !is_negative_literal
416+
&& !matches!(sub.flat_tokens(), [tt::TokenTree::Leaf(_)])
405417
&& sub.try_into_subtree().is_none_or(|it| {
406418
it.top_subtree().delimiter.kind == tt::DelimiterKind::Invisible
407419
});

0 commit comments

Comments
 (0)