Currently, even though macro expansion is done during the parse phase of the compiler it does not fully inline the production because if the ending of macro is an if block a following else block is not paired up with it.
I have been told that this is intended, though I believe that it is rather strange behaviour, because if someone was to output the --extended=pretty output of the compiler from said macro expansion it would look like the else block should match up.
Motivation:
If this was allowed then macro writers would have a very nice and clean way to have an optional fallout case that is syntactically nice to look at.
Example:
Lets say you want to write an initialiser for an object that relies on some item but have the option for a default value that is written by the user, with the else block you could write the following:
let item = init_foo!{ parms } else { Foo::new(15) };
Here the initialisation might go ahead normally but if not there is a custom default value.
If this applies to all macros by default, then this leaks an implementation detail of the macro. Changing a macro that expands to an if or if let to expand to something else (e.g., a match, or an if ... else ...) would be a breaking change in that world. That doesn't sound desirable. Macros that do want to offer this option can allow it in current Rust with slightly different syntax by explicitly accepting a trailing else ... in its input (example).
I understand that it could leak implementation details however, that could be seen by just directly outputting the macro - expanded output from the compiler.
It could be blocked by outputting a blank block at the end.
I don't see how a match statement would be able to take advantage of this
I understand that it could leak implementation details however, that could be seen by just directly outputting the macro - expanded output from the compiler.
You can look at the expanded output but you can't write Rust code that depends on it. Well, theoreitcally you could invoke rustc from a build script, pass the unstable compiler option, and compile the output, but (1) the output of pretty-expanded often can't be compiled as-is for various reasons and (2) by doing this you're pretty clearly far outside any reasonably stability guarantees.
It could be blocked by outputting a blank block at the end.
Yes but this is a burden for all macro authors. They'd have to be aware of it and do it. (And what about macros that are already written?)
I don't see how a match statement would be able to take advantage of this
I mean if a macro expands to if let with no else, then one could presumably stick an else after the macro invocation, and that would break if the macro definition changes to use a match instead of if let.
I understand. This should be opt-inable I think for those reasons. From my knowledge of compilers macro_rules could always output that extra block unless told not to.
Yeah an opt-in would resolve those concerns. Of course, there are other concerns, e.g., the evergreen "is it worth the added complexity?"
From my knowledge of compilers macro_rules could always output that extra block unless told not to.
Possibly but if there is an opt-in that the compiler knows about, it can just implement it more directly than by emulating the hacks a library author would have to use.
Of course, though I have not looked into that part of the compiler I would have to imagine that we are currently explicitly not allowing this since from a strictly syntax perspective this probably should have already been the case.
As for the evergreen question: I believe so since one of the nice things about rust is the consistent and pleasant looking syntax and I find that really complex macros do not have this. This change would help with some of that
I have thought about this some more.
For Macros2.0 we will now be declaring macros like other blocks. Similarly to functions or structs so a derive would make sense as the way to signal to the compiler this feature.
Example:
#derive(plop)
macro unless (expr: cond { expr: do})
...
(Pretty sure that this macro isn't valid but I think it gets my point across)
And if a macro derives plop then it is allowed to attach itself to external syntax and still be valid. Example:
unless!(foo { doBar();})
else unless!(bar { doFoo();})
else { doFooBar(); }
@Centril Because I do not know, what does a cc mean in this context?
I believe they are just notifying a related thread. Mentioning the GitHub issue leaves a note in the timeline on that issue.
@Nokel81 I believe it stems from the email field "CC" ("Carbon Copy") which is used to send the message to related third parties to keep them informed.
@mark-i-m @golddranks Thank you. I was really asking if I should join in on the conversation on their side but from what you say that is not exactly what was being offered. More to just observe.
@Nokel81 If you care about the future of macros, which from this issue it seems you do, I totally think you should join in on the "other side" (the other issue).