Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upEager expansion of macros #1628
Conversation
nrc
added
the
T-lang
label
May 24, 2016
nrc
self-assigned this
May 24, 2016
This comment has been minimized.
This comment has been minimized.
|
Is it a "macro 2.0"-only feature or will it be backported to |
This comment has been minimized.
This comment has been minimized.
|
I think it's kind of cute that |
This comment has been minimized.
This comment has been minimized.
|
@kennytm primarily a macro 2.0 feature. If it is not too much implementation work and doesn't break backwards compatibility (which I don't think it does), then we could backport. |
This comment has been minimized.
This comment has been minimized.
comex
commented
May 25, 2016
•
|
Can anyone explain the advantage of not always eagerly expanding macros? Alternately, why only allow this inside macro definitions? concat_idents is not the only use case for having a macro expand to something other than a full item/expression/etc. (And the limit could be trivially circumvented by putting the entire file inside a macro definition, if necessary!) |
This comment has been minimized.
This comment has been minimized.
|
(Just asking about the semantics, not that this feature is important :: ) Would this be valid? macro a {
(0) => { 1, 2, 3 };
(1) => { [$!a(0)] };
}
fn main() {
let m = a!(1);
}Would this be valid? macro b {
(0) => { , };
(1) => { [1 $!b(0) 2 $!b(0) 3] };
}
fn main() {
let m = b!(1);
} |
This comment has been minimized.
This comment has been minimized.
|
The two other syntax choices I've seen for this feature are |
Manishearth
reviewed
May 26, 2016
| not be obvious when to use either flavour. | ||
|
|
||
|
|
||
| # Alternatives |
This comment has been minimized.
This comment has been minimized.
Manishearth
May 26, 2016
Member
Alternative: macro-level $let which lets you do things like $$let $x = concat_idents(...); foo!($x). This does the same thing as eager expansion, but is more readable.
This comment has been minimized.
This comment has been minimized.
eddyb
May 26, 2016
Member
Binding is orthogonal to eager expansion, though, e.g. you might want to use $let for a handful of (unexpanded) tokens to reuse them a few times.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Ooh, doubling the |
This comment has been minimized.
This comment has been minimized.
|
As long as this can only be used inside macros, |
This comment has been minimized.
This comment has been minimized.
|
Getting into the syntax bikeshed - I like |
This comment has been minimized.
This comment has been minimized.
|
@kennytm I think both uses would be valid. I should add a note to the RFC about recursive use. I guess we would bail when we detect a cycle of expansion, rather than a cycle of names. |
This comment has been minimized.
This comment has been minimized.
|
@comex I don't think there are technical reasons for not eagerly expanding all macros. But regular expansion just feels more natural. There are some subtle differences with hygiene, I wonder if they might cause issues if all macros were done that way. To allow macros in any position macro expansion would have to happen on tokens, rather than on the AST. That would prohibit modularisation for macros and make hygiene much more complex, if not impossible. |
This comment has been minimized.
This comment has been minimized.
|
So from @kennytm's examples, eager expansion drops the requirement that macros expand to a full expr/item/type/etc. |
This comment has been minimized.
This comment has been minimized.
comex
commented
May 27, 2016
•
|
@nrc Hmm... I reread the RFC again and read your blog post about scopes... still a bit confused. The limitations you mention seem like they would also apply to the contents of a macro definition. Does eager expansion happen on tokens? I guess you sidestep the issue by not allowing names defined within a token list that gets eagerly expanded to affect macro resolution from that same eager expansion... (Which also means that performing the same process on the entire file first would be mostly useless, as no non-builtin macros could be in scope yet.) What happens if you try, though? macro bar { () => { macro baz { ... } } }
macro foo { () => { $!bar() } }What scopes does Is there a way to 'escape' expansions, so that in this example macro bar { ($mname:ident) => { macro $mname { $!test() } } }(Or if it's always part of the inner macro definition, then what if the word If eager expansions are nested, does the whole thing look up macros based on the innermost non-eager expansion's scope? Getting into pedantry a bit... Is it possible for an eager expansion to have unbalanced braces/parens? e.g. what happens if you write $!foo($!include("parens.rs") $!bar())will (on second thought, allowing that would kind of break the world anyway... since then you could exit the scope of the macro definition you're in) |
This comment has been minimized.
This comment has been minimized.
I would like to see This is pretty much the only way I see forward for being able to define macros from macros (modulo some name resolution magic around |
This comment has been minimized.
This comment has been minimized.
|
@comex The question would be whether eager expansion should be done before lexing or after it. If expansion is done after lexing, |
This comment has been minimized.
This comment has been minimized.
|
If Or, since this is "macro 2.0", we would assume #1566 is implemented already, and all syntax extensions (including those in libstd) are migrated to the libmacro API, which produces TokenStream. |
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Jul 18, 2016
|
Has any consensus been reached on this? For me, this would be an extremely desirable feature that would go a long way towards uncrippling the current macro system. Macros 2.0 will be great, but a long way off, of course. |
This comment has been minimized.
This comment has been minimized.
|
@alexreg The prerequisites will be reached for macros 1.1 (cc @alexcrichton and @nrc) so eager expansion should be doable then, although it might remain unstable for a while. |
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Jul 18, 2016
|
Thanks for the update. That’s good to hear. Any timeframe for that?
|
nrc
added
the
I-nominated
label
Aug 18, 2016
This comment has been minimized.
This comment has been minimized.
|
Hear ye, hear ye! This RFC is now entering final comment period with an inclination to accept. Summary of discussion follows:
@rust-lang/lang members, please check off your name to signal agreement. Leave a comment with concerns or objections. Others, please leave comments. Thanks!
|
nikomatsakis
added
final-comment-period
and removed
I-nominated
labels
Aug 22, 2016
This comment has been minimized.
This comment has been minimized.
|
re syntax, I still prefer my original proposal, but could also live with re scoping,
This is a hygiene question somewhat orothogonal to this RFC and the answer hasn't been completely nailed down anywhere yet. My current understanding is that, as written,
There is not. For nested macros, there is no proposal for escaping variables, there should be and when that happens, the same mechanism should apply to eager expansions too.
No, never, macros operate on token trees and they do not admit unbalanced delimiters. |
This comment has been minimized.
This comment has been minimized.
Can we formalize this? Perhaps we could say say something like "an eager macro invocation expands to a single token tree which is merged with the node containing the invocation", à la unquote-splicing. edit upon more thought, it's probably just regular unquote. |
This comment has been minimized.
This comment has been minimized.
|
At that point "eager" starts being meaningless, I'd almost call it |
This comment has been minimized.
This comment has been minimized.
|
@jseyfried if we mock up a syntax to generalize this (The restriction to macro definitions is just a narrow case of |
carols10cents
added this to Merge proposed
in Tracker
Apr 26, 2017
This comment has been minimized.
This comment has been minimized.
|
@nrc: given the relative lack of bandwidth around macros, I think we should consider postponing this RFC (until someone has the time to take up the mantle). What do you think? |
This comment has been minimized.
This comment has been minimized.
jseyfried
commented
Jul 17, 2017
•
|
I think we should postpone until proc-macros have the API to eagerly expand token streams and then see if a third-party |
This comment has been minimized.
This comment has been minimized.
|
@rfcbot fcp postpone I agree with @jseyfried and @aturon that it makes sense to wait here. I remain pretty conflicted about this proposal in any case, as has been previously discussed on thread. @nrc -- feel free to object, however. =) |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Jul 17, 2017
•
|
Team member @nikomatsakis has proposed to postpone this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
rfcbot
added
the
proposed-final-comment-period
label
Jul 17, 2017
This comment has been minimized.
This comment has been minimized.
|
So much for my dream of one day being able to concatenate idents in declarative macros... |
This comment has been minimized.
This comment has been minimized.
|
I agree we can postpone, I still think this is the best solution though. I think that if someone wanted to implement this (behind a flag, obvs) then that should be fine too and might offer some insight into the details (plus of course usage experience). |
This comment has been minimized.
This comment has been minimized.
|
Also, why does GitHub not offer me a sadface emoji? |
This comment has been minimized.
This comment has been minimized.
|
I've checked the review box for @pnkfelix, who is on PTO for an extended period. |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Jul 20, 2017
|
|
rfcbot
added
final-comment-period
and removed
proposed-final-comment-period
labels
Jul 20, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Jul 30, 2017
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
|
Closing as postponed. We'll definitely be revisiting this topic! |
aturon
closed this
Aug 9, 2017
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Aug 23, 2018
|
Hey @nrc. Per our discussion on Discord, could we get this reopened, with a view to merging it soon? I put my hand up to implement this, of course, and feel I'm in a good position to do so given my experience discussing this over many months, and my previous work with the macro system. I'll also draft a separate RFC for some new libstd macros at the same time (to do with hygiene manipulation). |
This comment has been minimized.
This comment has been minimized.
|
My read of this thread is that the lang team is divided on the design here; its not implementation bandwidth that led it to be postponed. (I myself am totally undecided!) |
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Aug 24, 2018
|
@withoutboats Okay, that certainly wasn't clear from the above, but I'm glad that's made plain now, thanks. So, it sounds like more discussion is needed then. I had some conservations with @nrc lately... a few points seemed to come up in discussion:
Shall we reopen so we can at least discuss it more? Maybe address some of the above points, and your present concerns, would be the best thing. |
This comment has been minimized.
This comment has been minimized.
Both of these options are perfectly acceptable to me. |
This comment has been minimized.
This comment has been minimized.
vi
commented
Aug 24, 2018
•
|
Is easer expansion a good idea not for only working around some missing feature (ident-position), but also as a tool to push DRY further, when repetitions happen inside a foreign macro call? |
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Aug 24, 2018
•
Good to know. Personally I'm also relatively happy with either. Would like to get some other @rust-lang/lang members' feedback on these points too though. |
This comment has been minimized.
This comment has been minimized.
alexreg
commented
Aug 24, 2018
|
@vi Not sure what you mean... |
This comment has been minimized.
This comment has been minimized.
vi
commented
Aug 25, 2018
|
@alexreg, I mean implementing macros to work within other non-cooperating macros. |
nrc commentedMay 24, 2016
This RFC proposes eager expansion of macros. The primary motivation is providing a mechanism for creating new identifiers in macros (e.g., by concatenating identifiers). It is not currently practical to do this because macros cannot be used in identifier position.