@@ -53,7 +53,11 @@ enables macro re-export (see below). It is [implemented and
53
53
tested] ( https://github.com/kmcallister/rust/commits/macro-reexport ) but needs a
54
54
rebase.
55
55
56
- ## Crate scope for macros
56
+ We can add a lint to warn about cases where an exported macro has paths that
57
+ are not absolute-with-crate or ` $crate ` -relative. This will have some
58
+ (hopefully rare) false positives.
59
+
60
+ ## Macro scope
57
61
58
62
In this document, the "syntax environment" refers to the set of syntax
59
63
extensions that can be invoked at a given position in the crate. The names in
@@ -63,55 +67,48 @@ However, the exclamation point is really part of the invocation syntax, not the
63
67
name, and some syntax extensions are invoked with no exclamation point, for
64
68
example item decorators like ` deriving ` .
65
69
66
- Imported macros will not automatically end up in the syntax environment.
67
- Instead, you can bring an imported macro into the syntax environment by
68
- providing the crate ident and a macro name (or wildcard) in a ` use macro ` view
69
- item:
70
+ We introduce an attribute ` use_macros ` to specify which macros from an external
71
+ crate should be imported to the syntax environment:
70
72
71
73
``` rust
72
- use macro std :: vec;
73
- use macro std :: panic as fail;
74
- use macro core :: * ;
75
- ```
76
-
77
- These paths must have exactly two components: the crate ident, and a macro name
78
- or ` * ` .
74
+ #[use_macros(vec, panic= " fail" )]
75
+ extern crate std;
79
76
80
- The syntax environment still consists of unqualified names. There's no way to
81
- invoke a macro through a qualified name. This obviates the need to change the
82
- parsing of expressions, patterns, etc.
83
-
84
- ` macro ` is a new keyword. This is an important part of the proposal, because
85
- it signals that we're deviating from usual name resolution. ` use macro ` is a
86
- memorable and searchable name for the feature.
77
+ #[use_macros(* )]
78
+ extern crate core;
79
+ ```
87
80
88
- The ` use macro ` view item only affects the syntax environment of the block or
89
- module where it appears, and only from the point of appearance onward. Unlike
90
- a normal ` use ` item, this includes child modules (in the same file or others).
81
+ Macros imported this way can be used anywhere in the module after the
82
+ ` extern crate ` item, including in child modules. Since a macro-importing
83
+ ` extern crate ` must appear at the crate root, and view items come before
84
+ other items, this effectively means imported macros will be visible for
85
+ the entire crate.
91
86
92
- Many macros expand using other "private macros" as an implementation detail.
87
+ Many macros expand using other "helper macros" as an implementation detail.
93
88
For example, librustc's ` declare_lint! ` uses ` lint_initializer! ` . The client
94
89
should not know about this macro, although it still needs to be exported for
95
- cross-crate use. For this reason we allow ` use macro ` within a macro
90
+ cross-crate use. For this reason we allow ` #[use_macros] ` on a macro
96
91
definition.
97
92
98
93
``` rust
99
94
/// Not to be imported directly.
100
- extern macro_rules! lint_initializer { ... }
95
+ #[export]
96
+ macro_rules! lint_initializer { ... }
101
97
102
98
/// Declare a lint.
103
- extern macro_rules! declare_lint {
104
- use macro $ crate :: lint_initializer;
105
-
99
+ #[export]
100
+ #[use_macros( lint_initializer)]
101
+ macro_rules! declare_lint {
106
102
($ name : ident , $ level : ident , $ desc : expr ) => (
107
103
static $ name : & 'static $ crate :: lint :: Lint
108
104
= & lint_initializer! ($ name , $ level , $ desc );
109
105
)
110
106
}
111
107
```
112
108
113
- The macro ` lint_initializer! ` will be visible only during further expansion of
114
- the result of invoking ` declare_lint! ` .
109
+ The macro ` lint_initializer! ` , imported from the same crate as ` declare_lint! ` ,
110
+ will be visible only during further expansion of the result of invoking
111
+ ` declare_lint! ` .
115
112
116
113
Procedural macros need their own way to manipulate the syntax environment, but
117
114
that's an unstable internal API, so it's outside the scope of this RFC.
@@ -120,43 +117,40 @@ that's an unstable internal API, so it's outside the scope of this RFC.
120
117
121
118
We also clean up macro syntax in a way that complements the semantic changes above.
122
119
123
- ## Macro definition syntax
120
+ ## ` #[use_macros(...)] mod `
124
121
125
- ` macro_rules! ` already allows ` { } ` for the macro body, but the convention is
126
- ` ( ) ` for some reason. In accepting this RFC we would change to a ` { } `
127
- convention for consistency with the rest of the language.
128
-
129
- The new macro can be used immediately. There is no way to ` use macro ` a macro
130
- defined in the same crate, and no need to do so.
131
-
132
- A macro with a ` pub ` qualifier, i.e.
122
+ The ` use_macros ` attribute can be applied to a ` mod ` item as well. The
123
+ specified macros will "escape" the module and become visible throughout the
124
+ rest of the enclosing module, including any child modules. A crate might start
125
+ with
133
126
134
127
``` rust
135
- pub macro_rules! foo { ... }
128
+ #[use_macros(* )]
129
+ mod macros ;
136
130
```
137
131
138
- escapes the syntax environment for the enclosing block/module and becomes
139
- available throughout the rest of the crate (according to depth-first search).
140
- This is like putting ` #[macro_escape] ` on the module and all its ancestors, but
141
- applies * only* to the macro with ` pub ` .
132
+ to define some macros for use by the whole crate, without putting those
133
+ definitions in ` lib.rs ` .
142
134
143
- ## Macro export and re-export
144
-
145
- A macro definition qualified by ` extern ` becomes available to other crates.
146
- That is, it can be the target of ` use macro ` . Or put another way,
147
- ` extern macro_rules! ` works the way ` #[macro_export] macro_rules! ` does today.
148
- Adding ` extern ` has no effect on the syntax environment for the current crate.
135
+ Note that ` #[use_macros(*)] ` is equivalent to the current ` #[macro_escape] ` .
136
+ However, the new convention is to use an outer attribute, in the file whose
137
+ syntax environment is affected, rather than an inner attribute in the file
138
+ defining the macros.
149
139
150
- ` pub ` and ` extern ` may be used together on the same macro definition, since
151
- their effects are independent.
140
+ ## Macro export and re-export
152
141
153
- We can also re-export macros that were imported from another crate. This is
154
- accomplished with ` extern use macro ` .
142
+ A macro definition qualified by ` #[export] ` becomes available to other crates.
143
+ That is, it can be the target of ` #[use_macros] ` . Or put another way,
144
+ ` #[export] macro_rules! ` works the way ` #[macro_export] macro_rules! ` does
145
+ today. Adding ` #[export] ` has no effect on the syntax environment for the
146
+ current crate.
155
147
156
- For example, libcollections defines a ` vec! ` macro, which would now look like:
148
+ We can also re-export macros that were imported from another crate. For
149
+ example, libcollections defines a ` vec! ` macro, which would now look like:
157
150
158
151
``` rust
159
- extern macro_rules! vec {
152
+ #[export]
153
+ macro_rules! vec {
160
154
($ ($ e : expr ),* ) => ({
161
155
let mut _temp = $ crate :: vec :: Vec :: new ();
162
156
$ (_temp . push ($ e );)*
@@ -169,7 +163,8 @@ Currently, libstd duplicates this macro in its own `macros.rs`. Now it could
169
163
do
170
164
171
165
``` rust
172
- extern use macro collections :: vec;
166
+ #[reexport_macros(vec)]
167
+ extern crate collections;
173
168
```
174
169
175
170
as long as the module ` std::vec ` is interface-compatible with
@@ -184,11 +179,6 @@ works" as soon as `$crate` is available. It's implemented as part of the
184
179
185
180
## ` #[plugin] ` attribute
186
181
187
- Since macros no longer automatically pollute the syntax environment, we can
188
- load them from every ` extern crate ` . (Probably we should exclude
189
- ` extern crate ` s that aren't at the crate root, because there's no way ` $crate `
190
- paths will be correct.)
191
-
192
182
` #[phase(plugin)] ` becomes simply ` #[plugin] ` and is still feature-gated. It
193
183
only controls whether to search for and run a plugin registrar function. The
194
184
plugin itself will decide whether it's to be linked at runtime, by calling a
@@ -208,39 +198,23 @@ to the plugin through a `Registry` method. This facilitates plugin
208
198
configuration. The alternative in many cases is to use interacting side
209
199
effects between procedural macros, which are harder to reason about.
210
200
211
- # Miscellaneous remarks
212
-
213
- In a future where macros are scoped the same way as other items,
214
-
215
- ``` rust
216
- use macro std :: vec;
217
- ```
218
-
219
- would become a deprecated synonym for
201
+ ## Syntax convention
220
202
221
- ``` rust
222
- use std :: vec ! ;
223
- ```
203
+ ` macro_rules! ` already allows ` { } ` for the macro body, but the convention is
204
+ ` ( ) ` for some reason. In accepting this RFC we would change to a ` { } `
205
+ convention for consistency with the rest of the language.
224
206
225
- Maintaining this synonym does not seem like a large burden.
207
+ ## Reserve ` macro ` as a keyword
226
208
227
- We can add a lint to warn about cases where an ` extern ` macro has paths that
228
- are not absolute-with-crate or ` $crate ` -relative. This will have some
229
- (hopefully rare) false positives, and is not fully fleshed out yet .
209
+ A lot of the syntax alternatives discussed for this RFC involved a ` macro `
210
+ keyword. The consensus is that macros are too unfinished to merit using the
211
+ keyword now. However, we should reserve it for a future macro system .
230
212
231
213
# Implementation and transition
232
214
233
215
I will coordinate implementation of this RFC, and I expect to write most of the
234
216
code myself.
235
217
236
- Some of the syntax cleanups could be deferred until after 1.0. However the
237
- semantic changes are enough that many users will re-examine and perhaps edit a
238
- large fraction of their macro definitions. My thinking is that the cleaned-up
239
- syntax should be available when this happens rather than requiring a separate
240
- pass a few months later. Also I would really like the first Rust release to
241
- put its best foot forward with macros, not just in terms of semantics but
242
- with a polished and pleasant user experience.
243
-
244
218
To ease the transition, we can keep the old syntax as a deprecated synonym, to
245
219
be removed before 1.0.
246
220
@@ -282,15 +256,9 @@ reform. Two ways this could work out:
282
256
283
257
# Unresolved questions
284
258
285
- Should we forbid ` $crate ` in non-` extern ` macros? It seems useless, however I
286
- think we should allow it anyway, to encourage the habit of writing ` $crate:: `
287
- for any references to the local crate.
288
-
289
- Should we allow ` pub use macro ` , which would escape the enclosing block/module
290
- the way ` pub macro_rules! ` does?
291
-
292
- Should we require that ` extern use macro ` can only appear in the crate root?
293
- It doesn't make a lot of sense to put it elsewhere.
259
+ Should we forbid ` $crate ` in non-` #[export] ` ed macros? It seems useless,
260
+ however I think we should allow it anyway, to encourage the habit of writing
261
+ ` $crate:: ` for any references to the local crate.
294
262
295
263
# Acknowledgements
296
264
0 commit comments