Update docs
This commit is contained in:
parent
34b995d9e2
commit
78e841d8b1
@ -1,14 +1,5 @@
|
||||
% 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.
|
||||
@ -46,19 +37,18 @@ lightweight custom syntax extensions, themselves defined using the
|
||||
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);
|
||||
// ...
|
||||
@ -109,10 +99,10 @@ that could be invoked like: `my_macro!(i->(( 2+2 )))`.
|
||||
|
||||
## 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,
|
||||
@ -166,12 +156,11 @@ separator token (a comma-separated list could be written `$(...),*`), and `+`
|
||||
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 {
|
||||
$(
|
||||
@ -180,7 +169,7 @@ macro_rules! early_return(
|
||||
_ => {}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
// ...
|
||||
early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
|
||||
// ...
|
||||
@ -228,7 +217,6 @@ solves the problem.
|
||||
Now consider code like the following:
|
||||
|
||||
~~~~
|
||||
# #![feature(macro_rules)]
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
# struct T2 { body: T3 }
|
||||
# enum T3 { Good2(uint), Bad2}
|
||||
@ -255,8 +243,7 @@ a match, but with a syntax that suits the problem better. The following macro
|
||||
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
|
||||
@ -275,7 +262,7 @@ macro_rules! biased_match (
|
||||
_ => { $err }
|
||||
};
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
# struct T2 { body: T3 }
|
||||
@ -297,13 +284,12 @@ like this, we might prefer to write a single macro invocation. The input
|
||||
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
|
||||
@ -320,24 +306,22 @@ process the semicolon-terminated lines, one-by-one. So, we want the following
|
||||
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
|
||||
@ -345,10 +329,9 @@ 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 ; )*
|
||||
@ -366,10 +349,10 @@ macro_rules! biased_match_rec (
|
||||
);
|
||||
// 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
|
||||
@ -388,7 +371,7 @@ macro_rules! biased_match (
|
||||
binds $( $bind_res ),*
|
||||
);
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
@ -434,9 +417,7 @@ As an example, `loop` and `for-loop` labels (discussed in the lifetimes guide)
|
||||
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 {
|
||||
@ -444,7 +425,7 @@ macro_rules! loop_x (
|
||||
$e
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
'x: loop {
|
||||
@ -467,22 +448,30 @@ lexical-order traversal of a crate's source. So a macro defined at module scope
|
||||
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
|
||||
|
||||
@ -490,22 +479,22 @@ mod foo {
|
||||
// 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
|
||||
}
|
||||
@ -514,8 +503,58 @@ mod bar {
|
||||
# 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
|
||||
|
||||
|
@ -31,10 +31,14 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc.
|
||||
|
||||
A plugin is a dynamic library crate with a designated "registrar" function that
|
||||
registers extensions with `rustc`. Other crates can use these extensions by
|
||||
loading the plugin crate with `#[phase(plugin)] extern crate`. See the
|
||||
loading the plugin crate with `#[plugin] extern crate`. See the
|
||||
[`rustc::plugin`](rustc/plugin/index.html) documentation for more about the
|
||||
mechanics of defining and loading a plugin.
|
||||
|
||||
Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by
|
||||
rustc itself. They are provided to the plugin through the `Registry`'s [`args`
|
||||
method](rustc/plugin/registry/struct.Registry.html#method.args).
|
||||
|
||||
# Syntax extensions
|
||||
|
||||
Plugins can extend Rust's syntax in various ways. One kind of syntax extension
|
||||
@ -105,10 +109,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
Then we can use `rn!()` like any other macro:
|
||||
|
||||
```ignore
|
||||
#![feature(phase)]
|
||||
#![feature(plugin)]
|
||||
|
||||
#[phase(plugin)]
|
||||
extern crate roman_numerals;
|
||||
#[plugin] extern crate roman_numerals;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(rn!(MMXV), 2015);
|
||||
@ -217,8 +220,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
Then code like
|
||||
|
||||
```ignore
|
||||
#[phase(plugin)]
|
||||
extern crate lint_plugin_test;
|
||||
#[plugin] extern crate lint_plugin_test;
|
||||
|
||||
fn lintme() { }
|
||||
```
|
||||
|
@ -668,9 +668,11 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']'
|
||||
| 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 `$`.)
|
||||
@ -2002,8 +2004,6 @@ type int8_t = i8;
|
||||
|
||||
### 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
|
||||
@ -2066,23 +2066,43 @@ On `struct`s:
|
||||
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.
|
||||
@ -2569,15 +2589,6 @@ The currently implemented features of the reference compiler are:
|
||||
* `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
|
||||
@ -2588,15 +2599,10 @@ The currently implemented features of the reference compiler are:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user