Update docs

This commit is contained in:
Keegan McAllister 2015-01-02 20:05:30 -08:00
parent 34b995d9e2
commit 78e841d8b1
3 changed files with 140 additions and 93 deletions

View File

@ -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

View File

@ -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() { }
```

View File

@ -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