An attribute is metadata attached to part of a program. Built-in attributes control compilation, code generation and tools, and macros can define more (Reference: Attributes, Conditional compilation).
Syntax
InnerAttribute: # ! [ Attr ]
OuterAttribute: # [ Attr ]
Attr:
SimplePath AttrInput?
| unsafe ( SimplePath AttrInput? )
AttrInput:
DelimTokenTree
| = Expression
- Outer attributes (
#[…]) apply to the form that follows. - Inner attributes (
#![…]) apply to the form they are declared within, such as a module or crate. - Active attributes remove themselves from the form they are on
during processing.
cfg,cfg_attrand attribute macros are active; all others are inert. - Tool attributes such as
#[rustfmt::skip]and#[clippy::…]are for external tools.
#![allow(unused)] // inner: the whole module
#[derive(Debug, Clone)] // outer: the following struct
pub struct Point { x: i32, y: i32 }
#[inline]
#[must_use = "this returns a new value"]
pub fn twice(x: i32) -> i32 { x * 2 }
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(super::twice(2), 4);
}
}
Unsafe attributes
Some attributes can break safety and are written #[unsafe(…)].
no_mangle, export_name and link_section must
use that form in edition 2024, and may use it in earlier editions.
#[unsafe(naked)] marks a naked function.
#[unsafe(no_mangle)]
pub extern "C" fn entry() {}
Built-in attributes
| Group | Attribute | Meaning |
|---|---|---|
| Conditional compilation | cfg | Keeps or removes the form (see below) |
cfg_attr | Conditionally applies other attributes | |
| Testing | test | Marks a function as a test |
ignore | Disables a test function | |
should_panic | Passes the test only if it panics | |
| Derive | derive | Invokes derive macros (see below) |
automatically_derived | Marks an implementation created by a derive | |
| Macros | macro_export | Exports a macro_rules macro across crates |
macro_use | Widens macro scope, or imports macros from a crate | |
proc_macro | Defines a function-like macro | |
proc_macro_derive | Defines a derive macro | |
proc_macro_attribute | Defines an attribute macro | |
| Diagnostics | allow, expect, warn, deny, forbid | Set the level of a lint |
deprecated | Generates deprecation notices; takes since and note | |
must_use | Lints against unused values or unused results | |
diagnostic::on_unimplemented | Suggests a message when a trait is not implemented | |
diagnostic::do_not_recommend | Hides an implementation from error messages | |
| ABI, linking, symbols and FFI | link | Names a native library for an extern block |
link_name | Sets the symbol name of a function or static in an extern block | |
link_ordinal | Sets a symbol’s ordinal | |
no_link | Prevents linking an extern crate | |
repr | Controls type layout | |
crate_type | Sets the kind of crate built | |
crate_name | Sets the crate name | |
no_main | Disables the main symbol | |
export_name | Sets the exported symbol name | |
link_section | Sets the object file section for a function or static | |
no_mangle | Disables symbol name encoding | |
used | Keeps a static in the output object file | |
| Code generation | inline | A hint to inline code; also inline(always) and inline(never) |
cold | A hint that a function is unlikely to be called | |
naked | Prevents the compiler emitting a function prologue and epilogue | |
no_builtins | Disables use of certain built-in functions | |
target_feature | Configures platform-specific code generation | |
track_caller | Passes the caller’s location to Location::caller() | |
instruction_set | Sets the instruction set used for a function | |
| Documentation | doc | Holds documentation; doc comments become this |
| Preludes | no_std | Removes std from the prelude |
no_implicit_prelude | Disables prelude lookups within a module | |
| Modules | path | Sets the file of a module |
| Limits | recursion_limit | Sets the maximum depth of certain compile-time operations |
type_length_limit | Sets the maximum size of a generic type | |
| Runtime | panic_handler | Sets the function that handles panics in no_std |
global_allocator | Sets the global memory allocator | |
windows_subsystem | Sets the Windows subsystem to link with | |
| Features | feature | Enables an unstable compiler feature, on the nightly compiler only |
| Type system | non_exhaustive | Says a type may gain fields or variants, so users cannot rely on matching all of them |
| Debugger | debugger_visualizer | Embeds a file describing debugger output |
collapse_debuginfo | Controls how macro invocations are encoded in debug information |
Conditional compilation
ConfigurationPredicate:
ConfigurationOption | ConfigurationAll | ConfigurationAny | ConfigurationNot | true | false
ConfigurationOption: IDENTIFIER ( = ( STRING_LITERAL | RAW_STRING_LITERAL ) )?
ConfigurationAll: all ( ConfigurationPredicateList? )
ConfigurationAny: any ( ConfigurationPredicateList? )
ConfigurationNot: not ( ConfigurationPredicate )
A predicate evaluates to true or false using options set when the crate is compiled.
all() is true when empty; any() is false when empty. Code
inside the crate cannot set options; rustc --print cfg --target TARGET
lists them for a target.
| Option | Values |
|---|---|
target_arch | "x86", "x86_64", "arm", "aarch64", "wasm32" and others |
target_feature | CPU features such as "avx2", "sse2", "crt-static" |
target_os | "windows", "macos", "ios", "linux", "android", "freebsd", "none" and others |
target_family | "unix", "windows", "wasm"; may be set more than once |
unix, windows | Name-only options, set for those families |
target_env | "", "gnu", "msvc", "musl" and others |
target_abi | "", "llvm", "eabihf", "abi64" and others |
target_endian | "little", "big" |
target_pointer_width | "16", "32", "64" |
target_vendor | "apple", "pc", "unknown" and others |
target_has_atomic | "8", "16", "32", "64", "128", "ptr" |
test | Set when compiling with --test |
debug_assertions | Set by default without optimisations |
proc_macro | Set when compiling a proc-macro crate |
panic | "unwind", "abort" |
feature = "name" is a Cargo convention for optional features and is not
defined by the compiler.
| Form | Use |
|---|---|
#[cfg(predicate)] | Removes the item if the predicate is false. May be used anywhere attributes are allowed |
#[cfg_attr(predicate, attrs…)] | Expands to the attributes if true, otherwise to nothing. Cannot be used with crate_type or crate_name |
cfg!(predicate) | Evaluates to the literal true or false. Both branches of an if cfg!(…) are still compiled |
cfg_select! { … } | Keeps the payload of the first arm whose predicate is true (Rust 1.95). _ is a fallback; it is an error if no arm matches |
#[cfg(target_os = "linux")]
fn only_on_linux() {}
#[cfg(all(unix, target_pointer_width = "64"))]
fn on_64bit_unix() {}
#[cfg(not(feature = "std"))]
extern crate core as std;
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(not(windows), path = "unix.rs")]
mod os;
let kind = if cfg!(unix) { "unix" } else { "other" };
derive
#[derive(…)] calls derive macros, which generate items, usually trait
implementations, for a struct, enum or union. It may be repeated, and all the listed
macros are invoked. The compiler’s built-in derives are Clone,
Copy, Debug, Default, Eq,
Hash, Ord, PartialEq and
PartialOrd.
Each type parameter normally gets a bound on the derived trait, and each field is
handled by that trait. Default can be derived on an enum if one
unit variant is marked #[default].
#[derive(PartialEq, Clone)]
struct Foo<T> {
a: i32,
b: T,
}
// The PartialEq derive generates, in effect:
impl<T: PartialEq> PartialEq for Foo<T> {
fn eq(&self, other: &Foo<T>) -> bool {
self.a == other.a && self.b == other.b
}
}
Other crates can provide derive macros, as serde does. See
Procedural macros.