Closed antonok-edm closed 4 months ago
I added the two dbg to the following code:
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
// `=> <expr>`
input.parse::<Token![=>]>()?;
+ dbg!(&input);
let expr = input.parse::<Expr>()?;
+ dbg!(&input);
// Commas after the expression are only optional if it's a `Block`
// or it is the last branch in the `match`.
And the output is:
[futures-macro/src/select.rs:62:13] &input = TokenStream [
Group {
delimiter: Brace,
stream: TokenStream [],
span: #0 bytes(10909..10911),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: #0 bytes(10924..10926),
},
Punct {
ch: '=',
spacing: Alone,
span: #0 bytes(10927..10928),
},
Ident {
ident: "pending",
span: #0 bytes(10929..10936),
},
Punct {
ch: ':',
spacing: Joint,
span: #0 bytes(10936..10937),
},
Punct {
ch: ':',
spacing: Joint,
span: #0 bytes(10937..10938),
},
Punct {
ch: '<',
spacing: Alone,
span: #0 bytes(10938..10939),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: #0 bytes(10939..10941),
},
Punct {
ch: '>',
spacing: Alone,
span: #0 bytes(10941..10942),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: #0 bytes(10942..10944),
},
Punct {
ch: '.',
spacing: Alone,
span: #0 bytes(10944..10945),
},
Ident {
ident: "fuse",
span: #0 bytes(10945..10949),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: #0 bytes(10949..10951),
},
Punct {
ch: '=',
spacing: Joint,
span: #0 bytes(10952..10953),
},
Punct {
ch: '>',
spacing: Alone,
span: #0 bytes(10953..10954),
},
Group {
delimiter: Brace,
stream: TokenStream [],
span: #0 bytes(10955..10957),
},
]
[futures-macro/src/select.rs:64:13] &input = TokenStream [
Punct {
ch: '=',
spacing: Joint,
span: #0 bytes(10952..10953),
},
Punct {
ch: '>',
spacing: Alone,
span: #0 bytes(10953..10954),
},
Group {
delimiter: Brace,
stream: TokenStream [],
span: #0 bytes(10955..10957),
},
]
error: expected `,`
--> futures/tests/async_await_macros.rs:402:41
|
402 | () = pending::<()>().fuse() => {}
| ^
It seems syn treats {} () = pending::<()>().fuse()
as a single expr.
cc @dtolnay
{} () = pending::<()>().fuse()
is a single expr.
macro_rules! expr {
($e:expr) => {};
}
expr!({} () = pending::<()>().fuse());
To parse this in a way that uses the expression termination rules of match arms, what you could do is: after parsing your =>
, collect all the rest of the tokens into a TokenStream prefixed with _ =>
, then parse syn::Arm
from that, and keep just the body
from that. Then repeat on whatever tokens are left.
I noticed that in the
select!
/select_biased!
macros, the unit type (()
) only works for the pattern-side of a branch in the first position.Consider the following minimal example:
It produces the following error (note: line 6 is the second branch):
This version compiles without issues: