-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decide on our long term/ideal goals for macros #440
Comments
cc @jbclements |
see also #416 |
I strongly agree that we need some consensus here. In particular, it seems like the macro system needs to be an ongoing project for a full-timer.... |
Off the top of my head:
Less sweeping issues (the line between this and the above is somewhat fuzzy):
|
I'm currently working on the macro parser issue; unfortunately, I'm also currently working on graduating and at least one other side project, so not much progress has been made recently. |
I added patterns a while back. |
@kmcallister Awesome; I'm sorry I forgot about that. |
A few more (some of which might be plain wrong):
|
|
Also, let the bike shedding begin, but I think |
@reem: Me too; it's in the RFC I'm drafting. |
@reem I agree, provided that we decide to make |
I saw this idea brought up a while back, and it's certainly something we should consider for 1.0: We could accomplish full macro hygiene by having all bindings other than those generated via input arguments to the macro be resolved in the lexical namespace the macro is defined in, rather than the one it is placed in. This has certain drawbacks, like using a macro causing you to silently adopt several new dependencies, but is a huge step forward because it would provide total hygiene, whereas today we have all kinds of problems with std/core and things like deriving with Encodable, Decodable, and serialize. Also, this was brought up on reddit but I'll repeat it here, but a stop-gap for full module namespacing of macros would be to namespace them under crates only and confine them to be define in |
Isn't that really hard to implement, especially cross-crate? |
@paulstansifer: I'm not sure what procedural macros will look like long-term, but it's plausible that they'll want a I think |
@paulstansifer I thought the patterns thing was for macro_rules. Syntax extensions can only be places on items I think, and not all of them (e.g., last time I checked, you could put one on a function, but not a method). Could you expand on how such a naming scheme would work please? I don't see how you can refer to a macro via a module path, when the set of modules can be arbitrarily changed by a syntax extension. Indeed, before running the syntax extensions, you don't even have a guarantee that the source will parse, only tokenise. Name hiding is a real footgun when using macros since it violates the usual mutability rules of rust. E.g.,
name hiding means that |
@reem that is my expectation for how macros should work. I would like to know why that is not the case - are there advantages to the current system? Or is it just the implementation effort? |
@reem That sounds pretty similar to the way that @jbclements made things work for |
@kmcallister Yeah, the advantage is that we have a pretty big syntactic space to play with inside |
@nick29581 Are you referring to attributes when you mentioned syntax extensions being placed on items? I haven't thought about attributes much; I probably owe them some study. I usually use "syntax extension" to refer to things like The rough shape of what I was imagining was that As for name hiding, I see what you mean, but I'm worried that the lint might give false positives in cases where the user writes a chain like |
For compiler plugins, I wonder if we need to have a more stable surface API for libsyntax, rather than forcing folks to delve into internal APIs that could change quite a bit as the compiler evolves. |
@bjz we definitely do - that is part of why we can't stabilise them for 1.0 |
@paulstansifer yes, I have been using 'syntax extension' to mean procedural macro, as opposed to macro_rules macros and built in macros. |
@paulstansifer so about the top-down expansion, that sounds like it would work, but also that it could be a bit surprising and unpredictable.It seems that we can either choose to go with top to bottom expansion and do procedural macros and macro_rules macros in the same phase, or allow forward references and separate the phases. The latter sounds better to me, since we should be able to spot any cycles and is more consistent with the rest of Rust. What are the advantages of going for the former arrangement? (I imagine it is more flexible, but I can't think of a use case off the top of my head. Are there expansion issues?) |
I disagree; if we are stabilising |
I think the idea is to make it ready before we stabilize. I'm against stabilizing if we still think it's not a good system by 1.0, that's just inviting a world of pain. |
@reem, see this blog post:
Efforts are to make |
@huonw and see my response :P
There are serious problems with |
@kmcallister's pending RFC and (partly) this issue are designed to clean up The 'current' in the blog post refers to the features of macro_rules at 1.0, not the features now. Also, as the blog post states, there's no reason we cannot have two similar macro definition systems, e.g. the legacy 1.0 |
I don't want to pick the ugly name just because we want to use the better name later. The likely outcome is that we're stuck with the ugly name for a long time I am pondering something like #[version(2)]
macro! foo ( ... ) |
I am definitely for changing the name to |
@blaenk: It's not negated, because it's still easier to keep track of version numbers rather than Anyway I was imagining you would need this only when defining a macro that uses features not stabilized in the 1.x branch. Another option is to include those in the crate-level |
I strongly disagree that it would be easier for people to have to remember the specific version number of the macro system which contains the features they want as opposed to a change in a perhaps descriptive name.
This is ultimately what everyone would want to be doing though, right? Wouldn't this then be required from that point forward, forever (to avoid breaking compatibility)? Or is this implying that at some point in the future, such as 2.0, the new macro system would become the default?
This sounds more reasonable to me from the perspective of someone writing macros. So this would be something like btw kmc I'm glad this is finally getting looked at/discussed and that you're part of it. |
@nick29581 Well, partially it's because that expansion ordering is what we currently do, and it's the "standard" way for macro systems to work (which means that we already have an idea how that expansion strategy cooperates with hygiene and other language features). But it's also more internally predictable: instead of having to remember how a macro was defined to figure out how name resolution will work, all macro name resolution will behave the same way. This also means that defining macros will be fully pluggable: Another part of the reason is more subjective: macro definitions will be more natural to topographically sort because people use macros and functions differently. It's natural and appropriate for a programmer to write lots and lots of functions that are only invoked in one place: functions provide code organization. But macros have little or no code organization power that functions don't have. What macros are good at is abstraction, which means that there are typically many macro invocations per definition, so there's no drive to put macro definitions right next to the invocation, since there isn't just one invocation. |
Can we add later phases for macro evaluation eventually so macros can operate on types and typed expressions, not just tokens? |
@ben0x539 It's an interesting thought, but I doubt that our typechecker would be able to cope with a not-fully-expanded program, and having a more conservative but totally consistent version of the typechecker seems like a big ask. And then there's the unintuitiveness of having the typechecker behave differently depending on when it's invoked, and having multiple different phases of macro expansion. Perhaps it would be possible to have a |
Why would that be? We could always claim a stub to |
This work on "modular macros" in OCaml may be of interest. |
Identifier concatenation/generation can be done without significantly complicating the rust parser by extending the existing substitution syntax ($prefexed names) to support macro invocations. |
#1738 (comment) already proposes |
Just mentioned in #1738 (comment) that a name for the current function name might be useful, so maybe a macro like |
I think that A limited |
It might be possible to provide something like |
I would like to bring to your attention the work of Chicken Scheme in this regard. I think they nailed it with their Explicit Renaming (opt-in hygiene) and Implicit Renaming (opt-out hygiene) procedural macro API. They are very simple to use and right to the point. Of course, a great part of that simplicity lies in Lisp's quasi-quotation syntax, which is probably not going to work for a language like Rust. (Or is it?) But the idea of having both explicit and implicit hygiene, with resp. opt-in and opt-out method calls, is neat.
A specific syntax extension (such as
On a more serious note, tail-call optimization would go a long way towards making |
I believe, with the Macros 2.0 RFC accepted, we can give this a close. Please let me know if that's wrong! |
@steveklabnik The proliferation of names here is very confusing. Which RFC is the Macros 2.0? |
I actually will be posting a blog post tomorrow about exactly this; I agree 100% The RFC is here: https://github.com/rust-lang/rfcs/blob/master/text/1566-proc-macros.md |
@steveklabnik proc-macros 2.0 and macros 2.0 are different beasts; I'm not sure that RFC solves this issue. We still (afaik) aren't sure what to do with macro!s 2.0. |
That RFC is in FCP right now: #1584 I assume that all the discussion that would have gone on in this issue would be on the actual RFC. |
Both macro_rules and syntax extensions, and other forms of syntactic fiddling. At the moment I don't have a good sense of what is intentional and what is accidental at the moment. I think these long term goals should inform our choice of what to do for 1.0.
cc @kmcallister @sfackler
The text was updated successfully, but these errors were encountered: