Closed
Description
This is a FIXME issue; currently, macro invocations are parsed too eagerly. In particular, the current system decides before expansion time whether a rhs pattern-use (e.g. $y) is bound or unbound. This is incompatible with macro-producing macros that use a given identifier in a pattern position. It's also incompatible with macros inside macros, where inner binding patterns are believed to be pattern uses. The solution is to delay this decision until the macro is encountered at expansion-time, by which time all outer macros have been expanded.
Here's an example of a macro that doesn't work in the current system:
// the z flows into and out of two macros (g & f) along one path, and one (just g) along the
// other, so the result of the whole thing should be "let z_123 = 3; z_123
macro_rules! g (
($x:ident) =>
(
{macro_rules! f(
($y:ident)=>({let $y=3;$x})
);
f!($x)})
)
fn a(){g!(z)}
Trying to expand this yields this error:
Running /usr/local/bin/rustc:
/tmp/g.rs:7:12: 7:13 error: unknown macro variable `y`
/tmp/g.rs:7 ($y:ident)=>({let $y=3;$x})
^
... indicating that the $y is believed to be a use, rather than a binder.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
Aatch commentedon Jun 8, 2013
Nominating for well-defined.
bblum commentedon Jul 23, 2013
double triage before triage meeting. i think this could maybe be well-covered; we understand how it should work, and it's not a backwards-compat hazard.
kud1ing commentedon Aug 9, 2013
I think the tag "A-macos" is unfortunate, since this is not Mac OS specific. Or is it?
huonw commentedon Aug 9, 2013
I imagine it's just a typo because
macos
is almostmacros
. It reproduces on linux. (Removed that tag.)kud1ing commentedon Aug 9, 2013
I guess so. Maybe rename "A-macos" to "A-mac_os" or "A-mac"?
catamorphism commentedon Aug 29, 2013
Accepted for milestone 3, feature-complete
jbclements commentedon Aug 30, 2013
Wow! glad to see this wind up on a milestone...
pnkfelix commentedon Mar 20, 2014
P-low, not 1.0.
huonw commentedon Jul 13, 2014
Would this be fixable by allowing
$
escapes? E.g.The
$$
's would "expand" to a single$
in the expanded code.jbclements commentedon Jul 13, 2014
No, don't go down that road; I don't believe that will lead to a nice solution.
huonw commentedon Jul 13, 2014
OK.
It would be nice if the eventual solution was not specific to nested
macro_rules!
, since one may wish to have a macro like e.g.foo (($e: expr) => { quote_expr!(cx, $$a + $e) })
(using the escaping for clarity), that is, substitute the passed in expression directly, but pass in a literal$a
forquote_expr
to handle internally...foo!(2)
should becomequote_expr!(cx, $a + 2)
.(I could easily imagine other more common procedural macros that may wish to "overload" the
$...
syntax, e.g. asql!(SELECT * FROM foo WHERE bar = $x)
macro.)jbclements commentedon Jul 13, 2014
Hang on... where is the $a bound, in your example?
12 remaining items
steveklabnik commentedon Apr 30, 2015
Triage: OP's code, with a semicolon, still generates the same error.
bltavares commentedon May 30, 2016
Triage: There is still the same error happening on
rustc 1.11.0-nightly (6e00b5556 2016-05-29)
Error:
macro_rules!
#34925B1Z0N commentedon Dec 31, 2022
It seem to be working poorly on variadic arguments. Or am I missing something?
CODE
Here