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 upRFC: Procedural macros 1.1 #1681
Conversation
alexcrichton
added
T-compiler
T-lang
labels
Jul 18, 2016
alexcrichton
self-assigned this
Jul 18, 2016
This comment has been minimized.
This comment has been minimized.
|
Suggestion: this might want to be titled Plugins 1.1, as it doesn't really impact the "macro" system (if you think of that as macro_rules, which I think many do). |
This comment has been minimized.
This comment has been minimized.
|
cc @jimmycuadra |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eddyb
reviewed
Jul 18, 2016
| * Sharing an API of the entire compiler | ||
| * Frozen interface between the compiler and macros | ||
|
|
||
| ### `librustc_macro` |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 18, 2016
Author
Member
This is currently done because macro is a keyword, and this doesn't propose changing that just yet. I was thinking that we could perhaps wholesale rename the crate one day as well if macro becomes an available name.
This comment has been minimized.
This comment has been minimized.
MovingtoMars
Jul 19, 2016
•
How about libmacros? This follows the approach that Go takes, ie the strings package.
sfackler
reviewed
Jul 18, 2016
|
|
||
| Like the rlib and dylib crate types, the `rustc-macro` crate | ||
| type is intended to be an intermediate product. What it *actually* produces is | ||
| not specified, but if a `-L` path is provided to it then the compiler will |
This comment has been minimized.
This comment has been minimized.
sfackler
Jul 18, 2016
Member
This feels a bit of an abuse of "link" if we switch plugins to IPC executables - maybe a separate flag would be a good idea?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 18, 2016
Author
Member
I believe the intention is that --extern works to load macros (it's what Cargo will pass), so this was just a natural extension of that. We could perhaps add something like -L macro=..., but at this point it doesn't seem strictly necessary as the compiler can always distinguish whether an artifact is a macro or an rlib.
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 18, 2016
Member
I believe -L for rustc means "library search path" not "link search path".
alexcrichton
reviewed
Jul 18, 2016
| } | ||
| impl TokenStream { | ||
| pub fn from_source(cx: &mut Context, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nrc
Jul 18, 2016
Member
I agree it may not be necessary. To be clear you must have some handle to the compiler, let's call that MacroContext, then either you can pass that around in the various functions, or you can leave it in TLS. The former is less ergonomic, but the later might have problems with multi-threaded macros and is arguably not as good engineering practice. I'm undecided as to which way we should swing in terms of the cost/benefit, but it would make a big difference to any libmacro APIs (methods vs free functions + the argument itself).
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 18, 2016
•
Member
Keep in mind that if you do interning with integer indices you can't even implement fmt::Debug on Token without putting something in TLS, and there is no meaningful difference between passing &mut MacroContext around and having it in TLS except for needing to set up TLS in each thread, as opposed to passing the context to one child thread, if needed.
If any TLS is used (as is now needed to impl Debug for Token), then the threading problems are unavoidable and having the context usable cross-thread would let users write broken code.
This comment has been minimized.
This comment has been minimized.
cgswords
Jul 18, 2016
In the discussion about parallel expansion, there needs to be a principled way to combine contexts / TLS: if a multi-threaded macro manages to manipualte its MacroContext in each of the threads (eg by interning things), combining these contexts in a principled way (eg unifying the interners and re-numbering some of the macro output) is basically the only way to place nice, anyway. To this end, it's TLS (or, more accurately, atomically-accessed globals) will end up the more ergonomic option.
eddyb
reviewed
Jul 18, 2016
| Like the executable, staticlib, and cdylib crate types, the `rustc-macro` crate | ||
| type is intended to be a final product. What it *actually* produces is not | ||
| specified, but if a `-L` path is provided to it then the compiler will recognize | ||
| the output artifacts as a macro and it can be loaded for a program. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Thanks @alexcrichton for the awesome writeup! We've been working for a while on some way enable usage of Serde and similar libraries on stable in the near term, without massive stabilization. For example, there's a code generation proposal (which sits entirely on the side from the macro/plugin system), as well as attempts to find a very small increment toward "macros 2.0". But this is the first proposal that can be implemented immediately, has a clear path toward speedy stabilization, and imposes virtually no maintenance burden. I'm incredibly excited to be so close to a solution for the biggest cause of nightly usage today. One thing that wasn't totally obvious to me, given that the macros 2.0 plan is a bit out of cache: what, if any, parts of what you propose to stabilize here would end up being deprecated once macros 2.0 has fully landed? (To be clear, I have zero problem stabilizing the small slice of functionality you've outlined here in the near term even if in the long term we plan to deprecate it.) |
eddyb
reviewed
Jul 18, 2016
| such as: | ||
|
|
||
| ```rust | ||
| extern crate double; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 18, 2016
Author
Member
cc @nrc, I think that importing custom derive annotations was a somewhat unspecified extension of "macros 2.0" right now, so to me it seems somewhat up in the air about whether we'd require that or not.
I don't mind one way or another, but I'm curious what @nrc thinks as well.
Eventually of course custom-derive will be imported through the normal module system I believe, so this is purely just a temporary stopgap.
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 18, 2016
Member
The problem is that if you do anything by default now, you'll need to opt out to be able to use the normal module system.
This comment has been minimized.
This comment has been minimized.
eddyb
reviewed
Jul 18, 2016
| ``` | ||
|
|
||
| Plugin authors would have to ensure that this is not naively interpreted as | ||
| `Baz = 1 + 1 * 2` as this will cause incorrect results. |
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 18, 2016
Member
Couldn't we add parenthesis around all such fragments at stringification time to avoid the misinterpretation?
Plugin authors can't do anything about this if all they have is conversion to String.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jul 18, 2016
Author
Member
Sure! This is just an implementation detail for the compiler though, right?
This comment has been minimized.
This comment has been minimized.
eddyb
Jul 18, 2016
Member
It's visible to the plugins (and stable code can observe it with stringify! right now), so adding extra parens should be specified somewhere.
nrc
changed the title
RFC: Macros 1.1
RFC: Procedural macros 1.1
Jul 18, 2016
This comment has been minimized.
This comment has been minimized.
This is a good question! Of the pieces here, what I would imagine is:
Other than that though I imagine these pieces to survive stabilization:
|
This comment has been minimized.
This comment has been minimized.
|
First, I don't think this RFC has gone through enough design, and fast-tracking it just to get people off of nightly is not a good idea, IMO. However, I am in favor of eventually (soon-ish) getting this sliver. Some of my specific issues: First: Second: Third: I don't like how macros are defined. I'd rather they be defined with something like |
This comment has been minimized.
This comment has been minimized.
|
@ubsan I don't like |
This comment has been minimized.
This comment has been minimized.
|
@ubsan |
This comment has been minimized.
This comment has been minimized.
|
I think On the integration level: plugins imply some form of host ABI. Stable plugins mean a stable |
This comment has been minimized.
This comment has been minimized.
|
@sfackler makes sense. I still don't think |
This comment has been minimized.
This comment has been minimized.
|
Do you have any suggestions for a better replacement? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
On naming: I see
As for the API: maybe have |
This comment has been minimized.
This comment has been minimized.
|
How does shoving Context into TLS hide implementation details? |
This comment has been minimized.
This comment has been minimized.
|
@sfackler The TLS slot wouldn't be exposed, the APIs would just not take any context. |
This comment has been minimized.
This comment has been minimized.
|
@ubsan's concern with |
This comment has been minimized.
This comment has been minimized.
|
Yeah. A |
This comment has been minimized.
This comment has been minimized.
|
Huzzah! The @rust-lang/lang team has decided to accept this RFC. We decided to ask @alexcrichton to move some of the detailed matters (e.g., prefixes, etc) into unresolved questions to be addressed during stabilization. Thanks everyone! |
nikomatsakis
referenced this pull request
Aug 22, 2016
Closed
Tracking issue for "Macros 1.1" (RFC #1681) #35900
nikomatsakis
merged commit ac22573
into
rust-lang:master
Aug 22, 2016
This comment has been minimized.
This comment has been minimized.
|
Tracking issue: rust-lang/rust#35900 If you'd like to keep following the development of this feature, please subscribe to that issue, thanks! :) |
nikomatsakis
added a commit
that referenced
this pull request
Aug 22, 2016
This comment has been minimized.
This comment has been minimized.
|
I still miss my comment about the inferior traceability of code through macros 1.1 as opposed to the current systems. Could we at least add it to the drawbacks section? |
This comment has been minimized.
This comment has been minimized.
|
@llogiq I pushed some text about spans |
This comment has been minimized.
This comment has been minimized.
|
Ok then. I'll keep an eye on the implementation. |
alexcrichton commentedJul 18, 2016
Extract a very small sliver of today's procedural macro system in the compiler,
just enough to get basic features like custom derive working, to have an
eventually stable API. Ensure that these features will not pose a maintenance
burden on the compiler but also don't try to provide enough features for the
"perfect macro system" at the same time. Overall, this should be considered an
incremental step towards an official "plugins 2.0".
Rendered