Yes. In particular the result must be a complete and (syntactically) valid expression, statement(s), item(s), impl item(s), or pattern. In an upcoming release (forget which), you can also expand to a type.
After all, if the input had to make sense, then the only thing you could feed to a macro would be already-valid syntax, which would rather limit what you could do with them, especially when you consider that macros possess no AST deconstruction abilities whatsoever.
macro_rules!
is a broadly working pile of code held together with preschool craft supplies. You know, the sort of tape and glue that doesn't so much bind two things together as mildly disincline them to come apart... unless you look at them too hard.
In particular, there are two salient things macro_rules!
is bad at:
-
It sucks at preventing you from writing macros that can parse code which might change meaning in the future. It makes some efforts to this end, but there are seriously holes big enough to drive a small planet through.
-
It sucks at giving you control over parsing.
The latest issue is type ascription: this takes the form expr : ty
. This is a problem because there are rules like this in the wild:
macro_rules! totally_legit {
($e:expr) => {...};
($i:ident : $t:ty) => {...};
}
Macros such as the above used to work, but no longer do, thus violating backward compatibility (and consequently, stability).
What sucks about this change in particular is that previously, there were ways to get around changes to macro parsing. This one, however, is 100% unfixable. If you have a macro that depends on rules like that, your only option is to throw out the macro and start again, you can't "fix" the rules such that existing code will continue to parse with the same meaning.
I might sound bitter about this. It's not at all because I've been actively working on a macro that relied on exactly this very rule and had to take an axe to it because of the change.
Nope.
...
eye twitches
Just to be clear: I'm sympathetic to the developer's position in all this. They have two options here: halt language changes until macro_rules!
gets replaced by something less dodgy (which could take who-knows how long), or sacrifice macro back-compat for the sake of highly desired language changes.
They're kinda damned if they do, damned if they don't.
...
Still pissed, though.
/me goes off to read this discussion and presumably to have his brain melt
So long as you don't go reading the source to custom_derive!
, you should be fine. Or anything written by IcyFoxy.
Ah, I was wondering about that. I also ran into a bit of a quirk when I tried to $crate::std::result::etc
, but I didn't have time to chase it down if I were going to get out the door in time for my flight this morning. Argh. I'll have to (a) fix that in the show notes and (b) see if I can figure out why it wasn't working right.
$crate
expands to either nothing or ::crate_name
where crate_name
is the imported name of the crate the macro comes from. So, for macros defined in std
, it expands to nothing if the macro is used inside the defining crate.
If you're referring to a type in std
, just use ::std::
as the prefix everywhere. If you're referring to a type in another crate, your best bet is to publicly re-export the necessary names in your own crate, then access them using $crate::
.
No problem.