Home Explore Blog CI



rustc

src/attributes.md
7410189167f4620a2c8af4590fee00f6c3e0112971ed095e0000000300000a8f
# Attributes

Attributes come in two types: *inert* (or *built-in*) and *active* (*non-builtin*).

## Builtin/inert attributes

These attributes are defined in the compiler itself, in
[`compiler/rustc_feature/src/builtin_attrs.rs`][builtin_attrs].

Examples include `#[allow]` and `#[macro_use]`.


These attributes have several important characteristics:
* They are always in scope, and do not participate in typical path-based resolution.
* They cannot be renamed. For example, `use allow as foo` will compile, but writing `#[foo]` will
  produce an error.
* They are 'inert', meaning they are left as-is by the macro expansion code.
  As a result, any behavior comes as a result of the compiler explicitly checking for their presence.
  For example, lint-related code explicitly checks for `#[allow]`, `#[warn]`, `#[deny]`, and
  `#[forbid]`, rather than the behavior coming from the expansion of the attributes themselves.

## 'Non-builtin'/'active' attributes

These attributes are defined by a crate - either the standard library, or a proc-macro crate.

**Important**: Many non-builtin attributes, such as `#[derive]`, are still considered part of the
core Rust language. However, they are **not** called 'builtin attributes', since they have a
corresponding definition in the standard library.

Definitions of non-builtin attributes take two forms:

1. Proc-macro attributes, defined via a function annotated with `#[proc_macro_attribute]` in a
   proc-macro crate.
2. AST-based attributes, defined in the standard library. These attributes have special 'stub'
   macros defined in places like [`library/core/src/macros/mod.rs`][core_macros].


These definitions exist to allow the macros to participate in typical path-based resolution - they
can be imported, re-exported, and renamed just like any other item definition. However, the body of
the definition is empty. Instead, the macro is annotated with the `#[rustc_builtin_macro]`
attribute, which tells the compiler to run a corresponding function in `rustc_builtin_macros`.

All non-builtin attributes have the following characteristics:
* Like all other definitions (e.g. structs), they must be brought into scope via an import.
  Many standard library attributes are included in the prelude - this is why writing `#[derive]`
  works without an import.
* They participate in macro expansion. The implementation of the macro may leave the attribute
  target unchanged, modify the target, produce new AST nodes, or remove the target entirely.

Chunks
74942e1c (1st chunk of `src/attributes.md`)
Title: Attributes: Built-in vs. Non-Built-in
Summary
Attributes in Rust are divided into two categories: built-in (inert) and non-built-in (active). Built-in attributes are defined within the compiler, are always in scope, cannot be renamed, and are inert during macro expansion. Non-built-in attributes are defined by crates, either through proc-macro attributes or AST-based attributes in the standard library. They must be brought into scope via import, participate in macro expansion, and their implementation can modify or remove the target.