-
Notifications
You must be signed in to change notification settings - Fork 507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expand Procedural Macro Docs #412
Changes from 19 commits
b6fa5e2
b3758ad
50d8cf4
36d6be1
ef6ca2b
0dd95e8
6f694fc
7f80970
6dbdc8c
9c0045f
6851fea
690bdee
8bb6ca3
58c49c7
caa8877
f800c04
19a988a
0a57ca9
5b27fac
f52d416
4dc54f2
981a1c3
f466d18
1975f82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,8 +35,7 @@ Attributes may appear as any of: | |
|
||
_Inner attributes_, written with a bang ("!") after the hash ("#"), apply to the | ||
item that the attribute is declared within. _Outer attributes_, written without | ||
the bang after the hash, apply to the item or generic parameter that follow the | ||
attribute. | ||
the bang after the hash, apply to the thing that follows the attribute. | ||
|
||
Attributes may be applied to many things in the language: | ||
|
||
|
@@ -82,6 +81,47 @@ fn some_unused_variables() { | |
} | ||
``` | ||
|
||
There are three kinds of attributes: | ||
|
||
* Built-in attributes | ||
* Macro attributes | ||
* Derive mode helper attributes | ||
|
||
## Dynamic and inert attributes | ||
|
||
An attribute is either dynamic or inert. During attribute processing, *dynamic | ||
attributes* remove themselves from the thing they are on while *inert attriutes* | ||
stay on. | ||
|
||
The `cfg` and `cfg_attr` attributes are dynamic. The `test` attribute is inert | ||
when compiling for tests and dynamic otherwise. Attribute macros are dynamic. | ||
All other attributes are inert. | ||
|
||
## Attribute resolution | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to avoid specifying any details here for now, the rules are not settled yet. |
||
|
||
On all things except for items, attribute resolution is straightforward. The | ||
`cfg` and `cfg_attr` attributes are applied and only inert attributes are | ||
allowed. Each of those inert attributes then resolve to either a built-in | ||
attribute or a derive mode helper attribute. If the attribute cannot resolve to | ||
either, it is an error. | ||
|
||
For items, attribute resolution is a bit more involved. First off, if there are | ||
any `cfg`, `cfg_attr`, or `test` attributes when not compiling tests, they are | ||
resolved first, and removed from the item. Then, each attribute is checked in | ||
the order they are written. If the attribute resolves to an inert attribute, | ||
check the next attribute. If the attribute resolves to a dynamic attribute, then | ||
perform its dynamic behavior. This will effectively replace the item with a new | ||
set of items that must go through attribute resolution from the beginning. If | ||
the attribute resolves to a macro that is not an attribute macro, it is an | ||
error. Otherwise, the attriute is not current resolveable. In this case, wait | ||
until another item brings the attribute into scope, and then recheck it. If all | ||
other items have their attributes resolved or are also waiting for attribute or | ||
derive mode resolution, it is an error. If all of the attributes are inert, then | ||
the item is finalized. If the item defines a new path for a macro, it is now | ||
available for other items. | ||
|
||
--- | ||
|
||
The rest of this page describes or links to descriptions of which attribute | ||
names have meaning. | ||
|
||
|
@@ -161,14 +201,20 @@ which can be used to control type layout. | |
|
||
- `macro_reexport` on an `extern crate` — re-export the named macros. | ||
|
||
- `macro_export` - export a macro for cross-crate usage. | ||
- `macro_export` - export a `macro_rules` macro for cross-crate usage. | ||
|
||
- `no_link` on an `extern crate` — even if we load this crate for macros, don't | ||
link it into the output. | ||
|
||
See the [macros section of the first edition of the | ||
book](../book/first-edition/macros.html#scoping-and-macro-importexport) for more | ||
information on macro scope. | ||
information on `macro_rules` macro scope. | ||
|
||
- `proc_macro` - Defines a [bang macro]. | ||
|
||
- `proc_macro_derive` - Defines a [derive macro]. | ||
|
||
- `proc_macro_attribute` - Defines an [attribute macro]. | ||
|
||
## Miscellaneous attributes | ||
|
||
|
@@ -525,9 +571,11 @@ You can implement `derive` for your own traits through [procedural macros]. | |
[match expressions]: expressions/match-expr.html | ||
[external blocks]: items/external-blocks.html | ||
[items]: items.html | ||
[attribute macro]: procedural-macros.html#attribute-macros | ||
[bang macro]: procedural-macros.html#bang-macros | ||
[conditional compilation]: conditional-compilation.html | ||
[trait]: items/traits.html | ||
[main]: crates-and-source-files.html | ||
[derive macro]: procedural-macros.html#derive-macros | ||
[trait]: items/traits.html[main]: crates-and-source-files.html | ||
[`Termination`]: ../std/process/trait.Termination.html | ||
[where clause]: items/where-clauses.html | ||
[trait or lifetime bounds]: trait-bounds.html |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
# Linkage | ||
|
||
The Rust compiler supports various methods to link crates together both | ||
> Note: This section is described more in terms of the compiler than of | ||
> the language. | ||
|
||
The compiler supports various methods to link crates together both | ||
statically and dynamically. This section will explore the various methods to | ||
link Rust crates together, and more information about native libraries can be | ||
link crates together, and more information about native libraries can be | ||
found in the [FFI section of the book][ffi]. | ||
|
||
[ffi]: ../book/ffi.html | ||
|
@@ -35,7 +38,7 @@ be ignored in favor of only building the artifacts specified by command line. | |
|
||
* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system | ||
library will be produced. This is different from other library outputs in that | ||
the Rust compiler will never attempt to link to `staticlib` outputs. The | ||
the compiler will never attempt to link to `staticlib` outputs. The | ||
purpose of this output type is to create a static library containing all of | ||
the local crate's code along with all upstream dependencies. The static | ||
library is actually a `*.a` archive on linux and osx and a `*.lib` file on | ||
|
@@ -44,28 +47,29 @@ be ignored in favor of only building the artifacts specified by command line. | |
dynamic dependencies on other Rust code. | ||
|
||
* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system | ||
library will be produced. This is used when compiling Rust code as | ||
library will be produced. This is used when compiling | ||
a dynamic library to be loaded from another language. This output type will | ||
create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on | ||
Windows. | ||
|
||
* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be | ||
produced. This is used as an intermediate artifact and can be thought of as a | ||
"static Rust library". These `rlib` files, unlike `staticlib` files, are | ||
interpreted by the Rust compiler in future linkage. This essentially means | ||
interpreted by the compiler in future linkage. This essentially means | ||
that `rustc` will look for metadata in `rlib` files like it looks for metadata | ||
in dynamic libraries. This form of output is used to produce statically linked | ||
executables as well as `staticlib` outputs. | ||
|
||
* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output | ||
produced is not specified, but if a `-L` path is provided to it then the | ||
compiler will recognize the output artifacts as a macro and it can be loaded | ||
for a program. If a crate is compiled with the `proc-macro` crate type it | ||
will forbid exporting any items in the crate other than those functions | ||
tagged `#[proc_macro_derive]` and those functions must also be placed at the | ||
crate root. Finally, the compiler will automatically set the | ||
`cfg(proc_macro)` annotation whenever any crate type of a compilation is the | ||
`proc-macro` crate type. | ||
for a program. Crates compiled with this crate type must only export | ||
[procedural macros]. The compiler will automatically set the `proc_macro` | ||
[configuration option]. The crates are always compiled with the same target | ||
that the compiler itself was built with. For example, if you are executing | ||
the compiler from Linux with an `x86_64` CPU, the target will be | ||
`x86_64-unknown-linux-gnu` even if the crate is a dependency of another crate | ||
being built for a different target. | ||
|
||
Note that these outputs are stackable in the sense that if multiple are | ||
specified, then the compiler will produce each form of output at once without | ||
|
@@ -124,7 +128,7 @@ dependencies will be used: | |
|
||
In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for | ||
all compilation needs, and the other options are just available if more | ||
fine-grained control is desired over the output format of a Rust crate. | ||
fine-grained control is desired over the output format of a crate. | ||
|
||
## Static and dynamic C runtimes | ||
|
||
|
@@ -205,3 +209,7 @@ a statically linked binary on MSVC you would execute: | |
```ignore,notrust | ||
RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc | ||
``` | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✂️ |
||
[configuration option]: conditional-compilation.html | ||
[procedural macros]: procedural-macros.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The full list is
cfg
,cfg_attr
,test
,bench
,derive
currently, if I'm not missing anything.test
andbench
are being migrated to macros right now though (rust-lang/rust#53410).(Also,
test
/bench
are always "dynamic", they tweak their target items in test mode as well - addpub
s, reexports.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps "active" would be better than "dynamic"?
Dynamic sounds like 1) something happening at runtime and 2) the attributes themselves are changing.
The difference with inert attributes is that "dynamic"/"active" attributes can transform their target items, i.e. change something else rather than themselves.
Perhaps we can even avoid "active built-in attributes" as a class and just call them "built-in attribute macros".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 on "active". I knew there was a better word. There always is when it comes to "dynamic". I just couldn't think of it.
I was going for "inert" as being attributes that remain on the item during macro resolution.
bench
isn't stable so we don't have to worry about it.derive
seems to act as an inert attribute to me. It doesn't get removed from the item when running the derivers/derive modes. It doesn't actually modify the item its own but produce new one. Likewise, the test attribute stays on when compiling tests.I'm not quite sure I want to call built-in attributes macro attributes as well.