Description
Calling Statement Macros with “return values”?
Macros can be used both for expressions and for sequences of statements. The latter being useful to create new definitions (e.g. one or even multiple let
clause(s)).
I’m observing that the general rule that expressions ending in a “Block” of type ()
don’t need a semicolon when used as a statement translates in a weird way to even macros with multiple statements. For example
macro_rules! s {
($x:ident) => {
let $x = 1;
"hello world"
}
}
can’t be used as s!{x}
. However s!{x};
does work (as does s!(x);
). I’m questioning how sensible it is to support these kind of macros since they have some kind of “return value”, whose type even is relevant for if they need a trailing ;
, while the “return value” cannot actually in any way (that I can think of) be retrieved.
A way nicer approach at resolving the non-working s!{x}
is of course to change the macro:
macro_rules! s {
($x:ident) => {
let $x = 1;
"hello world"; // ⟵ added semicolon
}
}
Ignored Semicolon
One (or at least I) would expect the macro m1
below to produce just a statement (judging from the semicolon), i.e. be illegal in expression context. However it somehow does pass as an expression, totally ignoring the semicolon. In the return position of a function it does produce ()
though [when called like m1!{}
– on the other hand m1!()
would still produce the integer].
macro_rules! m1 {
() => {
1;
}
}
macro_rules! m2 {
() => {
1
}
}
fn main() {
let x1 = m1!{};
println!("{}", x1);
let x2 = m1!{};
println!("{}", x2);
m1!();
m1!{}
m2!();
// m2!{} // illegal
m2!{};
m1!{} // apparently even returns ()
}
Output:
1
1
Errors:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.40s
Running `target/debug/playground`