% The Rust Macros Guide
-<div class="unstable-feature">
-<b>Warning:</b> There are currently various problems with invoking macros, how
-they interact with their environment, and how they are used outside of the
-location in which they are defined. Macro definitions are likely to change
-slightly in the future. For this reason, they are hidden behind the
-<code>macro_rules</code> <a href="reference.html#compiler-features">feature
-attribute</a>.
-</div>
-
# Introduction
Functions are the primary tool that programmers can use to build abstractions.
the pattern in the above code:
~~~~
-# #![feature(macro_rules)]
# enum T { SpecialA(uint), SpecialB(uint) }
# fn f() -> uint {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
-macro_rules! early_return(
+macro_rules! early_return {
($inp:expr $sp:path) => ( // invoke it like `(input_5 SpecialE)`
match $inp {
$sp(x) => { return x; }
_ => {}
}
);
-);
+}
// ...
early_return!(input_1 T::SpecialA);
// ...
## Invocation location
-A macro invocation may take the place of (and therefore expand to)
-an expression, an item, or a statement.
-The Rust parser will parse the macro invocation as a "placeholder"
-for whichever of those three nonterminals is appropriate for the location.
+A macro invocation may take the place of (and therefore expand to) an
+expression, item, statement, or pattern. The Rust parser will parse the macro
+invocation as a "placeholder" for whichever syntactic form is appropriate for
+the location.
At expansion time, the output of the macro will be parsed as whichever of the
three nonterminals it stands in for. This means that a single macro might,
instead of `*` to mean "at least one".
~~~~
-# #![feature(macro_rules)]
# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
# fn f() -> uint {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
-macro_rules! early_return(
+macro_rules! early_return {
($inp:expr, [ $($sp:path)|+ ]) => (
match $inp {
$(
_ => {}
}
)
-);
+}
// ...
early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
// ...
Now consider code like the following:
~~~~
-# #![feature(macro_rules)]
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
can solve the problem:
~~~~
-# #![feature(macro_rules)]
-macro_rules! biased_match (
+macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( ($e:expr) ~ ($p:pat) else $err:stmt ;
binds $bind_res:ident
_ => { $err }
};
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
pattern we want is clear:
~~~~
-# #![feature(macro_rules)]
# fn main() {}
-# macro_rules! b(
+# macro_rules! b {
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
binds $( $bind_res:ident ),*
)
-# => (0));
+# => (0) }
~~~~
However, it's not possible to directly expand to nested match statements. But
input patterns:
~~~~
-# #![feature(macro_rules)]
-# macro_rules! b(
+# macro_rules! b {
( binds $( $bind_res:ident ),* )
-# => (0));
+# => (0) }
# fn main() {}
~~~~
...and:
~~~~
-# #![feature(macro_rules)]
# fn main() {}
-# macro_rules! b(
+# macro_rules! b {
( ($e :expr) ~ ($p :pat) else $err :stmt ;
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
binds $( $bind_res:ident ),*
)
-# => (0));
+# => (0) }
~~~~
The resulting macro looks like this. Note that the separation into
piece of syntax (the `let`) which we only want to transcribe once.
~~~~
-# #![feature(macro_rules)]
# fn main() {
-macro_rules! biased_match_rec (
+macro_rules! biased_match_rec {
// Handle the first layer
( ($e :expr) ~ ($p :pat) else $err :stmt ;
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
);
// Produce the requested values
( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
-);
+}
// Wrap the whole thing in a `let`.
-macro_rules! biased_match (
+macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
binds $bind_res:ident
binds $( $bind_res ),*
);
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
will not clash. The following code will print "Hello!" only once:
~~~
-#![feature(macro_rules)]
-
-macro_rules! loop_x (
+macro_rules! loop_x {
($e: expr) => (
// $e will not interact with this 'x
'x: loop {
$e
}
);
-);
+}
fn main() {
'x: loop {
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
-If a module has the `macro_escape` attribute, its macros are also visible in
-its parent module after the child's `mod` item. If the parent also has
-`macro_escape` then the macros will be visible in the grandparent after the
-parent's `mod` item, and so forth.
+If a module has the `macro_use` attribute, its macros are also visible in its
+parent module after the child's `mod` item. If the parent also has `macro_use`
+then the macros will be visible in the grandparent after the parent's `mod`
+item, and so forth.
-Independent of `macro_escape`, the `macro_export` attribute controls visibility
-between crates. Any `macro_rules!` definition with the `macro_export`
-attribute will be visible to other crates that have loaded this crate with
-`phase(plugin)`. There is currently no way for the importing crate to control
-which macros are imported.
+The `macro_use` attribute can also appear on `extern crate`. In this context
+it controls which macros are loaded from the external crate, e.g.
+
+```rust,ignore
+#[macro_use(foo, bar)]
+extern crate baz;
+```
+
+If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
+there is no `#[macro_use]` attribute then no macros are loaded. Only macros
+defined with the `#[macro_export]` attribute may be loaded.
+
+To load a crate's macros *without* linking it into the output, use `#[no_link]`
+as well.
An example:
```rust
-# #![feature(macro_rules)]
-macro_rules! m1 (() => (()));
+macro_rules! m1 { () => (()) }
// visible here: m1
// visible here: m1
#[macro_export]
- macro_rules! m2 (() => (()));
+ macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
-macro_rules! m3 (() => (()));
+macro_rules! m3 { () => (()) }
// visible here: m1, m3
-#[macro_escape]
+#[macro_use]
mod bar {
// visible here: m1, m3
- macro_rules! m4 (() => (()));
+ macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
# fn main() { }
```
-When this library is loaded with `#[phase(plugin)] extern crate`, only `m2`
-will be imported.
+When this library is loaded with `#[use_macros] extern crate`, only `m2` will
+be imported.
+
+The Rust Reference has a [listing of macro-related
+attributes](reference.html#macro--and-plugin-related-attributes).
+
+# The variable `$crate`
+
+A further difficulty occurs when a macro is used in multiple crates. Say that
+`mylib` defines
+
+```rust
+pub fn increment(x: uint) -> uint {
+ x + 1
+}
+
+#[macro_export]
+macro_rules! inc_a {
+ ($x:expr) => ( ::increment($x) )
+}
+
+#[macro_export]
+macro_rules! inc_b {
+ ($x:expr) => ( ::mylib::increment($x) )
+}
+# fn main() { }
+```
+
+`inc_a` only works within `mylib`, while `inc_b` only works outside the
+library. Furthermore, `inc_b` will break if the user imports `mylib` under
+another name.
+
+Rust does not (yet) have a hygiene system for crate references, but it does
+provide a simple workaround for this problem. Within a macro imported from a
+crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
+By contrast, when a macro is defined and then used in the same crate, `$crate`
+will expand to nothing. This means we can write
+
+```rust
+#[macro_export]
+macro_rules! inc {
+ ($x:expr) => ( $crate::increment($x) )
+}
+# fn main() { }
+```
+
+to define a single macro that works both inside and outside our library. The
+function name will expand to either `::increment` or `::mylib::increment`.
+
+To keep this system simple and correct, `#[macro_use] extern crate ...` may
+only appear at the root of your crate, not inside `mod`. This ensures that
+`$crate` is a single identifier.
# A final note
| non_special_token ;
```
-User-defined syntax extensions are called "macros", and the `macro_rules`
-syntax extension defines them. Currently, user-defined macros can expand to
-expressions, statements, items, or patterns.
+`macro_rules` allows users to define syntax extension in a declarative way. We
+call such extensions "macros by example" or simply "macros" — to be distinguished
+from the "procedural macros" defined in [compiler plugins][plugin].
+
+Currently, macros can expand to expressions, statements, items, or patterns.
(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
any token other than a delimiter or `$`.)
### Module-only attributes
-- `macro_escape` - macros defined in this module will be visible in the
- module's parent, after this module has been included.
- `no_implicit_prelude` - disable injecting `use std::prelude::*` in this
module.
- `path` - specifies the file to load the module from. `#[path="foo.rs"] mod
remove any padding between fields (note that this is very fragile and may
break platforms which require aligned access).
+### Macro- and plugin-related attributes
+
+- `macro_use` on a `mod` — macros defined in this module will be visible in the
+ module's parent, after this module has been included.
+
+- `macro_use` on an `extern crate` — load macros from this crate. An optional
+ list of names `#[macro_use(foo, bar)]` restricts the import to just those
+ macros named. The `extern crate` must appear at the crate root, not inside
+ `mod`, which ensures proper function of the [`$crate` macro
+ variable](guide-macros.html#the-variable-$crate).
+
+- `macro_reexport` on an `extern crate` — re-export the named macros.
+
+- `macro_export` - export a macro for cross-crate usage.
+
+- `plugin` on an `extern crate` — load this crate as a [compiler
+ plugin][plugin]. The `plugin` feature gate is required. Any arguments to
+ the attribute, e.g. `#[plugin=...]` or `#[plugin(...)]`, are provided to the
+ plugin.
+
+- `no_link` on an `extern crate` — even if we load this crate for macros or
+ compiler plugins, don't link it into the output.
+
+See the [macros guide](guide-macros.html#scoping-and-macro-import/export) for
+more information on macro scope.
+
+
### Miscellaneous attributes
- `export_name` - on statics and functions, this determines the name of the
exported symbol.
- `link_section` - on statics and functions, this specifies the section of the
object file that this item's contents will be placed into.
-- `macro_export` - export a macro for cross-crate usage.
- `no_mangle` - on any item, do not apply the standard name mangling. Set the
symbol for this item to its identifier.
- `packed` - on structs or enums, eliminate any padding that would be used to
align fields.
-- `phase` - on `extern crate` statements, allows specifying which "phase" of
- compilation the crate should be loaded for. Currently, there are two
- choices: `link` and `plugin`. `link` is the default. `plugin` will [load the
- crate at compile-time][plugin] and use any syntax extensions or lints that the crate
- defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
- both at runtime and compiletime.
- `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute.
* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
nasty hack that will certainly be removed.
-* `macro_rules` - The definition of new macros. This does not encompass
- macro-invocation, that is always enabled by default, this
- only covers the definition of new macros. There are currently
- various problems with invoking macros, how they interact with
- their environment, and possibly how they are used outside of
- location in which they are defined. Macro definitions are
- likely to change slightly in the future, so they are
- currently hidden behind this feature.
-
* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers,
but the implementation is a little rough around the
edges, so this can be seen as an experimental feature
closure as `once` is unlikely to be supported going forward. So
they are hidden behind this feature until they are to be removed.
-* `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins
- for custom lints or syntax extensions. The implementation is
- considered unwholesome and in need of overhaul, and it is not clear
- what they will look like moving forward.
+* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions.
+ These depend on compiler internals and are subject to change.
-* `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it
- wants to load. As with `phase`, the implementation is
- in need of an overhaul, and it is not clear that plugins
- defined using this will continue to work.
+* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin].
* `quote` - Allows use of the `quote_*!` family of macros, which are
implemented very poorly and will likely change significantly