Closed
Description
Multi-statement macros (macros that expand to multiple statements) are hard to use because hygiene runs separately on each line, meaning it's very easy to "lose" identifiers.
Here are some examples. The macro is trying to declare a variable in the scope where it was called, but it takes multiple statements to construct.
/*
// no good: $n declared in inner scope
macro_rules! m {
($n:ident) => ({
let a = 1;
let $n = a;
})
}
*/
/*
// no good: hygiene throws away "a"
macro_rules! m {
($n:ident) => (
let a = 1;
let $n = a;
)
}
*/
// workaround
macro_rules! m {
($n:ident) => (
let $n = {
let a = 1;
a
};
)
}
fn main() {
m!(b);
println!("{}", b);
}
This is a long-standing bug, not a regression. I previously reported this here and here (can likely be closed) but it wasn't very visible. ping @Sgeo @chris-chambers
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
Sgeo commentedon Feb 24, 2016
I am experimentally playing with the idea of using hygiene to hide one object, then exposing another object that refers to the hidden object. The macro I have is
Trying to use this fails with
durka commentedon Feb 25, 2016
For the record, you can write code that relies on this bug. This code
produces code that looks the same under pretty-expansion, but
no_macro
(which represents what the code would look like were this bug fixed) prints 3, whileyes_macro
prints 2.Add test for issue rust-lang#31856
Add another test for issue rust-lang#31856
Rollup merge of rust-lang#32923 - jseyfried:fix_hygiene, r=nrc