Skip to content

Commit 29fae10

Browse files
committedJun 3, 2022
Auto merge of rust-lang#12451 - TimNN:double-dollar, r=Veykril
feat: Support `$$` in macros. The implementation mirrors what `rustc` currently does [1]. Part of rust-lang#11952. \[1]: https://github.com/rust-lang/rust/blob/0595ea1d12cf745e0a672d05341429ecb0917e66/compiler/rustc_expand/src/mbe/quoted.rs#L230-L241
2 parents d1968a3 + 40bfb29 commit 29fae10

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed
 

‎crates/hir-def/src/macro_expansion_tests/mbe.rs

+68
Original file line numberDiff line numberDiff line change
@@ -1544,3 +1544,71 @@ struct Foo;
15441544
"##]],
15451545
)
15461546
}
1547+
1548+
#[test]
1549+
fn test_dollar_dollar() {
1550+
check(
1551+
r#"
1552+
macro_rules! register_struct { ($Struct:ident) => {
1553+
macro_rules! register_methods { ($$($method:ident),*) => {
1554+
macro_rules! implement_methods { ($$$$($$val:expr),*) => {
1555+
struct $Struct;
1556+
impl $Struct { $$(fn $method() -> &'static [u32] { &[$$$$($$$$val),*] })*}
1557+
}}
1558+
}}
1559+
}}
1560+
1561+
register_struct!(Foo);
1562+
register_methods!(alpha, beta);
1563+
implement_methods!(1, 2, 3);
1564+
"#,
1565+
expect![[r#"
1566+
macro_rules! register_struct { ($Struct:ident) => {
1567+
macro_rules! register_methods { ($$($method:ident),*) => {
1568+
macro_rules! implement_methods { ($$$$($$val:expr),*) => {
1569+
struct $Struct;
1570+
impl $Struct { $$(fn $method() -> &'static [u32] { &[$$$$($$$$val),*] })*}
1571+
}}
1572+
}}
1573+
}}
1574+
1575+
macro_rules !register_methods {
1576+
($($method: ident), *) = > {
1577+
macro_rules!implement_methods {
1578+
($$($val: expr), *) = > {
1579+
struct Foo;
1580+
impl Foo {
1581+
$(fn $method()-> & 'static[u32] {
1582+
&[$$($$val), *]
1583+
}
1584+
)*
1585+
}
1586+
}
1587+
}
1588+
}
1589+
}
1590+
macro_rules !implement_methods {
1591+
($($val: expr), *) = > {
1592+
struct Foo;
1593+
impl Foo {
1594+
fn alpha()-> & 'static[u32] {
1595+
&[$($val), *]
1596+
}
1597+
fn beta()-> & 'static[u32] {
1598+
&[$($val), *]
1599+
}
1600+
}
1601+
}
1602+
}
1603+
struct Foo;
1604+
impl Foo {
1605+
fn alpha() -> & 'static[u32] {
1606+
&[1, 2, 3]
1607+
}
1608+
fn beta() -> & 'static[u32] {
1609+
&[1, 2, 3]
1610+
}
1611+
}
1612+
"#]],
1613+
)
1614+
}

‎crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ macro_rules! f2 { ($i:) => ($i) }
5656
f2!();
5757
macro_rules! f3 { ($i:_) => () }
5858
f3!();
59+
60+
macro_rules! m1 { ($$i) => () }
61+
m1!();
5962
"#,
6063
expect![[r#"
6164
macro_rules! i1 { invalid }
@@ -74,6 +77,9 @@ macro_rules! f2 { ($i:) => ($i) }
7477
/* error: invalid macro definition: missing fragment specifier */
7578
macro_rules! f3 { ($i:_) => () }
7679
/* error: invalid macro definition: missing fragment specifier */
80+
81+
macro_rules! m1 { ($$i) => () }
82+
/* error: invalid macro definition: `$$` is not allowed on the pattern side */
7783
"#]],
7884
)
7985
}

‎crates/mbe/src/parser.rs

+8
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
135135
let id = lit.id;
136136
Op::Var { name, kind, id }
137137
}
138+
tt::Leaf::Punct(punct @ tt::Punct { char: '$', .. }) => match mode {
139+
Mode::Pattern => {
140+
return Err(ParseError::unexpected(
141+
"`$$` is not allowed on the pattern side",
142+
))
143+
}
144+
Mode::Template => Op::Leaf(tt::Leaf::Punct(*punct)),
145+
},
138146
tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => {
139147
return Err(ParseError::expected("expected ident"))
140148
}

0 commit comments

Comments
 (0)
Please sign in to comment.