Skip to content

Commit

Permalink
Auto merge of rust-lang#12451 - TimNN:double-dollar, r=Veykril
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jun 3, 2022
2 parents d1968a3 + 40bfb29 commit 29fae10
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
68 changes: 68 additions & 0 deletions crates/hir-def/src/macro_expansion_tests/mbe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,3 +1544,71 @@ struct Foo;
"##]],
)
}

#[test]
fn test_dollar_dollar() {
check(
r#"
macro_rules! register_struct { ($Struct:ident) => {
macro_rules! register_methods { ($$($method:ident),*) => {
macro_rules! implement_methods { ($$$$($$val:expr),*) => {
struct $Struct;
impl $Struct { $$(fn $method() -> &'static [u32] { &[$$$$($$$$val),*] })*}
}}
}}
}}
register_struct!(Foo);
register_methods!(alpha, beta);
implement_methods!(1, 2, 3);
"#,
expect![[r#"
macro_rules! register_struct { ($Struct:ident) => {
macro_rules! register_methods { ($$($method:ident),*) => {
macro_rules! implement_methods { ($$$$($$val:expr),*) => {
struct $Struct;
impl $Struct { $$(fn $method() -> &'static [u32] { &[$$$$($$$$val),*] })*}
}}
}}
}}
macro_rules !register_methods {
($($method: ident), *) = > {
macro_rules!implement_methods {
($$($val: expr), *) = > {
struct Foo;
impl Foo {
$(fn $method()-> & 'static[u32] {
&[$$($$val), *]
}
)*
}
}
}
}
}
macro_rules !implement_methods {
($($val: expr), *) = > {
struct Foo;
impl Foo {
fn alpha()-> & 'static[u32] {
&[$($val), *]
}
fn beta()-> & 'static[u32] {
&[$($val), *]
}
}
}
}
struct Foo;
impl Foo {
fn alpha() -> & 'static[u32] {
&[1, 2, 3]
}
fn beta() -> & 'static[u32] {
&[1, 2, 3]
}
}
"#]],
)
}
6 changes: 6 additions & 0 deletions crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ macro_rules! f2 { ($i:) => ($i) }
f2!();
macro_rules! f3 { ($i:_) => () }
f3!();
macro_rules! m1 { ($$i) => () }
m1!();
"#,
expect![[r#"
macro_rules! i1 { invalid }
Expand All @@ -74,6 +77,9 @@ macro_rules! f2 { ($i:) => ($i) }
/* error: invalid macro definition: missing fragment specifier */
macro_rules! f3 { ($i:_) => () }
/* error: invalid macro definition: missing fragment specifier */
macro_rules! m1 { ($$i) => () }
/* error: invalid macro definition: `$$` is not allowed on the pattern side */
"#]],
)
}
Expand Down
8 changes: 8 additions & 0 deletions crates/mbe/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
let id = lit.id;
Op::Var { name, kind, id }
}
tt::Leaf::Punct(punct @ tt::Punct { char: '$', .. }) => match mode {
Mode::Pattern => {
return Err(ParseError::unexpected(
"`$$` is not allowed on the pattern side",
))
}
Mode::Template => Op::Leaf(tt::Leaf::Punct(*punct)),
},
tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => {
return Err(ParseError::expected("expected ident"))
}
Expand Down

0 comments on commit 29fae10

Please sign in to comment.