|
| 1 | +- Feature Name: macro |
| 2 | +- Start Date: 2016-04-17 |
| 3 | +- RFC PR: (leave this empty) |
| 4 | +- Rust Issue: (leave this empty) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Macros by example 2.0. A replacement for `macro_rules!`. This is mostly a |
| 10 | +placeholder RFC since many of the issues affecting the new macro system are |
| 11 | +(or will be) addressed in other RFCs. This RFC may be expanded at a later date. |
| 12 | + |
| 13 | +Currently in this RFC: |
| 14 | + |
| 15 | +* That we should have a new macro by example system, |
| 16 | +* a new keyword for declaring macros. |
| 17 | + |
| 18 | +In other RFCs: |
| 19 | + |
| 20 | +* Naming and modularisation (#1561). |
| 21 | + |
| 22 | +May be added to this RFC later (or might be separate RFCs): |
| 23 | + |
| 24 | +* more detailed syntax proposal, |
| 25 | +* hygiene improvements. |
| 26 | + |
| 27 | +Note this RFC does not involve procedural macros (aka syntax extensions). |
| 28 | + |
| 29 | + |
| 30 | +# Motivation |
| 31 | +[motivation]: #motivation |
| 32 | + |
| 33 | +There are several changes to the macro by example system which are desirable but |
| 34 | +backwards compatible (See [RFC 1561](https://github.com/rust-lang/rfcs/pull/1561) |
| 35 | +for some changes to macro naming and modularisation, I would also like to |
| 36 | +propose improvements to hygiene in macros, and some improved syntax). |
| 37 | + |
| 38 | +In order to maintain Rust's backwards compatibility guarantees, we cannot change |
| 39 | +the existing system (`macro_rules!`) to accommodate these changes. I therefore |
| 40 | +propose a new macro by example system to live alongside `macro_rules!`. |
| 41 | + |
| 42 | +Example (possible) improvements: |
| 43 | + |
| 44 | +```rust |
| 45 | +// Naming (RFC 1561) |
| 46 | + |
| 47 | +fn main() { |
| 48 | + a::foo!(...); |
| 49 | +} |
| 50 | + |
| 51 | +mod a { |
| 52 | + // Macro privacy (TBA) |
| 53 | + pub macro! foo { ... } |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +```rust |
| 58 | +// Relative paths (part of hygiene reform, TBA) |
| 59 | + |
| 60 | +mod a { |
| 61 | + pub macro! foo { ... bar() ... } |
| 62 | + fn bar() { ... } |
| 63 | +} |
| 64 | + |
| 65 | +fn main() { |
| 66 | + a::foo!(...); // Expansion calls a::bar |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +```rust |
| 71 | +// Syntax (TBA) |
| 72 | + |
| 73 | +macro! foo($a: ident) => { |
| 74 | + return $a + 1; |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +I believe it is extremely important that moving to the new macro system is as |
| 79 | +straightforward as possible for both macro users and authors. This must be the |
| 80 | +case so that users make the transition to the new system and we are not left |
| 81 | +with two systems forever. |
| 82 | + |
| 83 | +A goal of this design is that for macro users, there is no difference in using |
| 84 | +the two systems other than how macros are named. For macro authors, most macros |
| 85 | +that work in the old system should work in the new system with minimal changes. |
| 86 | +Macros which will need some adjustment are those that exploit holes in the |
| 87 | +current hygiene system. |
| 88 | + |
| 89 | + |
| 90 | +# Detailed design |
| 91 | +[design]: #detailed-design |
| 92 | + |
| 93 | +There will be a new system of macros by example using similar syntax and |
| 94 | +semantics to the current `macro_rules!` system. |
| 95 | + |
| 96 | +A macro by example is declared using the `macro` keyword with the `!` |
| 97 | +operator. For example, where a macro `foo` is declared today as `macro_rules! |
| 98 | +foo { ... }`, it will be declared using `macro! foo { ... }`. I leave the syntax |
| 99 | +of the macro body for later specification. |
| 100 | + |
| 101 | + |
| 102 | +# Drawbacks |
| 103 | +[drawbacks]: #drawbacks |
| 104 | + |
| 105 | +There is a risk that `macro_rules!` is good enough for most users and there is |
| 106 | +low adoption of the new system. Possibly worse would be that there is high |
| 107 | +adoption but little migration from the old system, leading to us having to |
| 108 | +support two systems forever. |
| 109 | + |
| 110 | + |
| 111 | +# Alternatives |
| 112 | +[alternatives]: #alternatives |
| 113 | + |
| 114 | +Make backwards incompatible changes to `macro_rules!`. This is probably a |
| 115 | +non-starter due to our stability guarantees. We might be able to make something |
| 116 | +work if this was considered desirable. |
| 117 | + |
| 118 | +Limit ourselves to backwards compatible changes to `macro_rules!`. I don't think |
| 119 | +this is worthwhile. It's not clear we can make meaningful improvements without |
| 120 | +breaking backwards compatibility. |
| 121 | + |
| 122 | +Don't use a keyword - either make `macro` not a keyword or use a different word |
| 123 | +for the macros by example syntax. |
| 124 | + |
| 125 | +Use `macro` instead of `macro!` (we might want to use bare `macro` for |
| 126 | +procedural macros, not clear if the overlap will be a problem). |
| 127 | + |
| 128 | +Live with the existing system. |
| 129 | + |
| 130 | + |
| 131 | +# Unresolved questions |
| 132 | +[unresolved]: #unresolved-questions |
| 133 | + |
| 134 | +What to do with `macro_rules`? We will need to maintain it at least until `macro!` |
| 135 | +is stable. Hopefully, we can then deprecate it (some time will be required to |
| 136 | +migrate users to the new system). Eventually, I hope we can remove `macro_rules!`. |
| 137 | +That will take a long time, and would require a 2.0 version of Rust to strictly |
| 138 | +adhere to our stability guarantees. |
| 139 | + |
| 140 | +There are many questions still to be answered as this RFC and some sister RFCs |
| 141 | +are developed. |
0 commit comments