|
| 1 | +# Attributes |
| 2 | + |
| 3 | +Attributes come in two types: *inert* (or *built-in*) and *active* (*non-builtin*). |
| 4 | + |
| 5 | +## Builtin/inert attributes |
| 6 | + |
| 7 | +These attributes are defined in the compiler itself, in |
| 8 | +[`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs]. |
| 9 | + |
| 10 | +Examples include `#[allow]` and `#[macro_use]`. |
| 11 | + |
| 12 | +[builtin_attrs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/builtin_attrs/index.html |
| 13 | + |
| 14 | +These attributes have several important characteristics: |
| 15 | +* They are always in scope, and do not participate in typical path-based resolution. |
| 16 | +* They cannot be renamed. For example, `use allow as foo` will compile, but writing `#[foo]` will |
| 17 | + produce an error. |
| 18 | +* They are 'inert', meaning they are left as-is by the macro expansion code. |
| 19 | + As a result, any behavior comes as a result of the compiler explicitly checking for their presence. |
| 20 | + For example, lint-related code explicitly checks for `#[allow]`, `#[warn]`, `#[deny]`, and |
| 21 | + `#[forbid]`, rather than the behavior coming from the expansion of the attributes themselves. |
| 22 | + |
| 23 | +## 'Non-builtin'/'active' attributes |
| 24 | + |
| 25 | +These attributes are defined by a crate - either the standard library, or a proc-macro crate. |
| 26 | + |
| 27 | +**Important**: Many non-builtin attributes, such as `#[derive]`, are still considered part of the |
| 28 | +core Rust language. However, they are **not** called 'builtin attributes', since they have a |
| 29 | +corresponding definition in the standard library. |
| 30 | + |
| 31 | +Definitions of non-builtin attributes take two forms: |
| 32 | + |
| 33 | +1. Proc-macro attributes, defined via a function annotated with `#[proc_macro_attribute]` in a |
| 34 | + proc-macro crate. |
| 35 | +2. AST-based attributes, defined in the standard library. These attributes have special 'stub' |
| 36 | + macros defined in places like [`library/core/src/macros/mod.rs`][core_macros]. |
| 37 | + |
| 38 | +[core_macros]: https://github.com/rust-lang/rust/blob/master/library/core/src/macros/mod.rs |
| 39 | + |
| 40 | +These definitions exist to allow the macros to participate in typical path-based resolution - they |
| 41 | +can be imported, re-exported, and renamed just like any other item definition. However, the body of |
| 42 | +the definition is empty. Instead, the macro is annotated with the `#[rustc_builtin_macro]` |
| 43 | +attribute, which tells the compiler to run a corresponding function in `rustc_builtin_macros`. |
| 44 | + |
| 45 | +All non-builtin attributes have the following characteristics: |
| 46 | +* Like all other definitions (e.g. structs), they must be brought into scope via an import. |
| 47 | + Many standard library attributes are included in the prelude - this is why writing `#[derive]` |
| 48 | + works without an import. |
| 49 | +* They participate in macro expansion. The implementation of the macro may leave the attribute |
| 50 | + target unchanged, modify the target, produce new AST nodes, or remove the target entirely. |
0 commit comments