mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-16 23:24:03 +00:00
Auto merge of #12451 - TimNN:double-dollar, r=Veykril
feat: Support `$$` in macros.
The implementation mirrors what `rustc` currently does [1]. Part of #11952.
\[1]: 0595ea1d12/compiler/rustc_expand/src/mbe/quoted.rs (L230-L241)
This commit is contained in:
commit
29fae10345
3 changed files with 82 additions and 0 deletions
|
@ -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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,9 @@ macro_rules! f2 { ($i:) => ($i) }
|
||||||
f2!();
|
f2!();
|
||||||
macro_rules! f3 { ($i:_) => () }
|
macro_rules! f3 { ($i:_) => () }
|
||||||
f3!();
|
f3!();
|
||||||
|
|
||||||
|
macro_rules! m1 { ($$i) => () }
|
||||||
|
m1!();
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
macro_rules! i1 { invalid }
|
macro_rules! i1 { invalid }
|
||||||
|
@ -74,6 +77,9 @@ macro_rules! f2 { ($i:) => ($i) }
|
||||||
/* error: invalid macro definition: missing fragment specifier */
|
/* error: invalid macro definition: missing fragment specifier */
|
||||||
macro_rules! f3 { ($i:_) => () }
|
macro_rules! f3 { ($i:_) => () }
|
||||||
/* error: invalid macro definition: missing fragment specifier */
|
/* error: invalid macro definition: missing fragment specifier */
|
||||||
|
|
||||||
|
macro_rules! m1 { ($$i) => () }
|
||||||
|
/* error: invalid macro definition: `$$` is not allowed on the pattern side */
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,14 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
|
||||||
let id = lit.id;
|
let id = lit.id;
|
||||||
Op::Var { name, kind, 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(_) => {
|
tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => {
|
||||||
return Err(ParseError::expected("expected ident"))
|
return Err(ParseError::expected("expected ident"))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue