-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DESIGN BUG] declarative macros lack of neat way to simulate lookahead within rust grammer syntax const X: Y
#130928
Comments
const X: Y
const X: Y
This part is not going to work: According to https://doc.rust-lang.org/reference/macros-by-example.html
But you can totally match it using something like incremental TT muncher. |
But problem is none of MacroFragSpec is working. I try with EVERY macro frag spec, end up with open an issue here.
macro_rules! echo_block {
(pub type $ident:ident<$($(gm:block)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_expr {
(pub type $ident:ident<$($(gm:expr)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_ident {
(pub type $ident:ident<$($(gm:ident)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_item {
(pub type $ident:ident<$($(gm:item)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_lifetime {
(pub type $ident:ident<$($(gm:lifetime)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_literal {
(pub type $ident:ident<$($(gm:literal)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_meta {
(pub type $ident:ident<$($(gm:meta)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_pat {
(pub type $ident:ident<$($(gm:pat)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_pat_param {
(pub type $ident:ident<$($(gm:pat_param)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_path {
(pub type $ident:ident<$($(gm:path)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_stmt {
(pub type $ident:ident<$($(gm:stmt)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_tt {
(pub type $ident:ident<$($(gm:tt)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
macro_rules! echo_ty {
(pub type $ident:ident<$($(gm:ty)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(gm)? $gi $(: $gt)?, )*> = $($tt)*;
};
}
echo_block!(pub type Foo2<T, const N: usize> = [T; N]);
echo_expr!(pub type Foo2<T, const N: usize> = [T; N]);
echo_ident!(pub type Foo2<T, const N: usize> = [T; N]);
echo_item!(pub type Foo2<T, const N: usize> = [T; N]);
echo_lifetime!(pub type Foo2<T, const N: usize> = [T; N]);
echo_literal!(pub type Foo2<T, const N: usize> = [T; N]);
echo_meta!(pub type Foo2<T, const N: usize> = [T; N]);
echo_pat!(pub type Foo2<T, const N: usize> = [T; N]);
echo_pat_param!(pub type Foo2<T, const N: usize> = [T; N]);
echo_path!(pub type Foo2<T, const N: usize> = [T; N]);
echo_stmt!(pub type Foo2<T, const N: usize> = [T; N]);
echo_tt!(pub type Foo2<T, const N: usize> = [T; N]);
echo_ty!(pub type Foo2<T, const N: usize> = [T; N]); |
You should be able to match Try searching for incremental tt muncher and implementing one. |
Awesome, inspire me to workaround with lookbehind. macro_rules! echo2 {
(@foo pub type $ident:ident<$($gi:ident $(lookahead_qualifier=$gq:tt)? $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($($gq)? $gi $(: $gt)?),*> = $($tt)*;
};
(@bar pub type $ident:ident<$($gi:ident $(lookahead_qualifier=$gq:tt)? $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($($gq)? $gi $(: $gt)?),*> = $($tt)*;
};
(@lookahead_workaround pub type $ident:ident<$($gi:ident $(lookahead_qualifier=$gq:tt)? $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($($gq)? $gi $(: $gt)?),*> = $($tt)*;
};
(pub type $ident:ident<$($(const)? $gi:ident $(: $gt:ty)?),*> = $($tt:tt)*) => {
pub type $ident<$($(const)? $gi $(: $gt)?),*> = $($tt)*;
};
}
// // TODO: https://github.com/rust-lang/rust/issues/130928
// echo2!(pub type Foo2<T, const N: usize> = [T; N]);
echo2!(@foo pub type Foo2<T, N lookahead_qualifier=const: usize> = [T; N]); |
But still think rust should provide basic look ahead like Because look ahead DOES exists in rust language syntax. Otherwise, declarative macro need to simulate look ahead leads to unreadable unmaintainable look ahead simulation code. |
const X: Y
const X: Y
const X: Y
const X: Y
I tried this code:
macro match and echo non
const X: Y
pattern is fine.But within current rust desgin, to let declarative macro match lookahead within rust grammer syntax
const X: Y
or input rust code, and do lookahead simulation
or input lookahead free dsl, and output lookahead code
I expected to see this happen:
const X: Y
Instead, this happened:
Need to simulate lookahead within rust grammer syntax
const X: Y
Leads to ugly simulation code.
Thus I think it's a design bug.
Meta
rustc --version --verbose
:Backtrace
related
Also found similar issue back to 2021 in
pin-project-lite
.So, I guess there is no way yet.
taiki-e/pin-project-lite#62
The text was updated successfully, but these errors were encountered: