Skip to content
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

Merged
merged 24 commits into from
Sep 7, 2018
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b6fa5e2
Expand documentation on procedural macros
alexcrichton Aug 23, 2018
b3758ad
Remove 'in Rust' in proc macros
Havvy Aug 25, 2018
50d8cf4
Notify cargo proc-macro crate info
Havvy Aug 25, 2018
36d6be1
Clarify proc macros as crate type, not crate
Havvy Aug 25, 2018
ef6ca2b
First pass removal of guide-level material
Havvy Aug 25, 2018
0dd95e8
Move proc-macro type sections to bottom
Havvy Aug 25, 2018
6f694fc
Improve proc_macro crate type docs
Havvy Aug 25, 2018
7f80970
Clean up language in linkage. Note about compiler specifiness
Havvy Aug 25, 2018
6dbdc8c
Add 'proc_macro' to configuation options
Havvy Aug 25, 2018
9c0045f
Add proc_macro attributes to attributes page
Havvy Aug 26, 2018
6851fea
Attribute resolution, types of attrs, inert/dynamic attrs
Havvy Aug 29, 2018
690bdee
Referencify proc_macro crate section
Havvy Aug 29, 2018
8bb6ca3
More referenceifying proc macros
Havvy Aug 30, 2018
58c49c7
Derive mode macros
Havvy Aug 31, 2018
caa8877
Attribute macros
Havvy Sep 1, 2018
f800c04
Runtime information of proc macros
Havvy Sep 1, 2018
19a988a
Function-like proc macros
Havvy Sep 2, 2018
0a57ca9
Cleanup proc macros after multi-day editing
Havvy Sep 2, 2018
5b27fac
Add proc macro attrs to attrs on fns list
Havvy Sep 2, 2018
f52d416
Remove attribute resolution for now
Havvy Sep 3, 2018
4dc54f2
Active attributes, not dynamic
Havvy Sep 3, 2018
981a1c3
macos => macros
Havvy Sep 4, 2018
f466d18
Proc macros: Fix tests, links, slight rewording, consistency
Havvy Sep 5, 2018
1975f82
Whitespace: Extra newline in linkage.md
Havvy Sep 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions src/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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
Copy link
Contributor

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 and bench 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 - add pubs, reexports.)

Copy link
Contributor

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".

Copy link
Contributor Author

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.

when compiling for tests and dynamic otherwise. Attribute macros are dynamic.
All other attributes are inert.

## Attribute resolution
Copy link
Contributor

Choose a reason for hiding this comment

The 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.
Macro modularization was stabilized, but there's still a number of incomplete items from rust-lang/rust#50911 (comment) that need to be done until beta, stable or maybe even later if crater allows.
(My suggestion would be to stash this section somewhere until 1.30 stable is released.)


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.

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
5 changes: 4 additions & 1 deletion src/conditional-compilation.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ The following configurations must be defined by the implementation:
This can be used to enable extra debugging code in development but not in
production. For example, it controls the behavior of the standard library's
`debug_assert!` macro.
* `proc_macro` - Set when the crate being compiled is being compiled with the
`proc_macro` [crate type].

You can also set another [attribute] based on a `cfg` variable with `cfg_attr`:

Expand All @@ -96,4 +98,5 @@ This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
Lastly, configuration options can be used in expressions by invoking the `cfg!`
macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise.

[attribute]: attributes.html
[attribute]: attributes.html
[crate type]: linkage.html
4 changes: 3 additions & 1 deletion src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ fn test_only() {

The attributes that have meaning on a function are [`cfg`], [`deprecated`],
[`doc`], `export_name`, `link_section`, `no_mangle`, [the lint check
attributes], [`must_use`], [the testing attributes], and [the optimization hint
attributes], [`must_use`], [the procedural macro attributes], [the testing
attributes], and [the optimization hint
attributes].

[external blocks]: items/external-blocks.html
Expand All @@ -147,6 +148,7 @@ attributes].
[attributes]: attributes.html
[`cfg`]: conditional-compilation.html
[the lint check attributes]: attributes.html#lint-check-attributes
[the procedural macro attributes]: procedural-macros.html
[the testing attributes]: attributes.html#testing
[the optimization hint attributes]: attributes.html#optimization-hints
[`deprecated`]: attributes.html#deprecation
Expand Down
32 changes: 20 additions & 12 deletions src/linkage.md
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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
```


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

[configuration option]: conditional-compilation.html
[procedural macros]: procedural-macros.html
Loading