Syntax
InnerAttribute :
#
!
[
Attr]
OuterAttribute :
#
[
Attr]
Attr :
SimplePath AttrInput?AttrInput :
DelimTokenTree
|=
LiteralExpressionwithout suffix
An attribute is a general, free-form metadatum that is interpreted according to name, convention, and language and compiler version. Attributes are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334 (C#).
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 thing that follows the attribute.
The attribute consists of a path to the attribute, followed by an optional
delimited token tree whose interpretation is defined by the attribute.
Attributes other than macro attributes also allow the input to be an equals
sign (=
) followed by a literal expression. See the meta item
syntax below for more details.
Attributes can be classified into the following kinds:
- Built-in attributes
- Macro attributes
- Derive macro helper attributes
- Tool attributes
Attributes may be applied to many things in the language:
- All item declarations accept outer attributes while external blocks, functions, implementations, and modules accept inner attributes.
- Most statements accept outer attributes (see Expression Attributes for limitations on expression statements).
- Block expressions accept outer and inner attributes, but only when they are the outer expression of an expression statement or the final expression of another block expression.
- Enum variants and struct and union fields accept outer attributes.
- Match expression arms accept outer attributes.
- Generic lifetime or type parameter accept outer attributes.
- Expressions accept outer attributes in limited situations, see Expression Attributes for details.
Some examples of attributes:
// General metadata applied to the enclosing module or crate.
#![crate_type = "lib"]
// A function marked as a unit test
#[test]
fn test_foo() {
/* ... */
}
// A conditionally-compiled module
#[cfg(target_os = "linux")]
mod bar {
/* ... */
}
// A lint attribute used to suppress a warning/error
#[allow(non_camel_case_types)]
type int8_t = i8;
// Inner attribute applies to the entire function.
fn some_unused_variables() {
#![allow(unused_variables)]
let x = ();
let y = ();
let z = ();
}
A "meta item" is the syntax used for the Attr rule by most built-in
attributes and the meta
macro fragment specifier. It has the following
grammar:
Syntax
MetaItem :
SimplePath
| SimplePath=
LiteralExpressionwithout suffix
| SimplePath(
MetaSeq?)
MetaSeq :
MetaItemInner (,
MetaItemInner )*,
?MetaItemInner :
MetaItem
| LiteralExpressionwithout suffix
Literal expressions in meta items must not include integer or float type suffixes.
Some examples of meta items are:
no_std
doc = "example"
cfg(any())
deprecated(since = "1.2.0", note = "text")
repr(align(32))
An attribute is either active or inert. During attribute processing, active attributes remove themselves from the thing they are on while inert attributes stay on.
The cfg
and cfg_attr
attributes are active. The test
attribute is inert
when compiling for tests and active otherwise. Attribute macros are active.
All other attributes are inert.
The rest of this page describes or links to descriptions of which attribute names have meaning.
Note: This section is in the process of being removed, with specific sections for each attribute. It is not the full list of crate-root attributes.
crate_name
- specify the crate's crate name.crate_type
- see linkage.no_builtins
- disable optimizing certain code patterns to invocations of library functions that are assumed to existno_main
- disable emitting themain
symbol. Useful when some other object being linked to definesmain
.no_start
- disable linking to thenative
crate, which specifies the "start" language item.recursion_limit
- Sets the maximum depth for potentially infinitely-recursive compile-time operations like auto-dereference or macro expansion. The default is#![recursion_limit="64"]
.windows_subsystem
- Indicates that when this crate is linked for a Windows target it will configure the resulting binary's subsystem via the linker. Valid values for this attribute areconsole
andwindows
, corresponding to those two respective subsystems. More subsystems may be allowed in the future, and this attribute is ignored on non-Windows targets.
On an extern
block, the following attributes are interpreted:
link
- indicate that a native library should be linked to for the declarations in this block to be linked correctly.link
supports an optionalkind
key with three possible values:dylib
,static
, andframework
. See external blocks for more about external blocks. Two examples:#[link(name = "readline")]
and#[link(name = "CoreFoundation", kind = "framework")]
.
On declarations inside an extern
block, the following attributes are
interpreted:
link_name
- the name of the symbol that this function or static should be imported as.
See type layout for documentation on the repr
attribute
which can be used to control type layout.
-
macro_use
on amod
— macros defined in this module will be visible in the module's parent, after this module has been included. -
macro_use
on anextern crate
— load macros from this crate. An optional list of names#[macro_use(foo, bar)]
restricts the import to just those macros named. Theextern crate
must appear at the crate root, not insidemod
, which ensures proper function of the$crate
macro variable. -
macro_export
- export amacro_rules
macro for cross-crate usage. -
no_link
on anextern crate
— even if we load this crate for macros, don't link it into the output. -
proc_macro
- Defines a function-like macro. -
proc_macro_derive
- Defines a derive macro. -
proc_macro_attribute
- Defines an attribute macro.
export_name
- on statics and functions, this determines the name of the exported symbol.global_allocator
- when applied to a static item implementing theGlobalAlloc
trait, sets the global allocator.link_section
- on statics and functions, this specifies the section of the object file that this item's contents will be placed into.no_mangle
- on any item, do not apply the standard name mangling. Set the symbol for this item to its identifier.used
- on statics, this forces the compiler to keep the variable in the output object file.panic_handler
— sets the function to handle panics.
The deprecated
attribute marks an item as deprecated. It has two optional
fields, since
and note
.
since
expects a version number, as in#[deprecated(since = "1.4.1")]
rustc
doesn't know anything about versions, but external tools likeclippy
may check the validity of this field.
note
is a free text field, allowing you to provide an explanation about the deprecation and preferred alternatives.
Only public items can be given the
#[deprecated]
attribute. #[deprecated]
on a module is inherited by all
child items of that module.
rustc
will issue warnings on usage of #[deprecated]
items. rustdoc
will
show item deprecation, including the since
version and note
, if available.
Here's an example.
#[deprecated(since = "5.2", note = "foo was rarely used. Users should instead use bar")]
pub fn foo() {}
pub fn bar() {}
The RFC contains motivations and more details.
The doc
attribute is used to document items and fields. Doc comments
are transformed into doc
attributes.
See The Rustdoc Book for reference material on this attribute.
The path
attribute says where a module's source file is. See modules for
more information.
The prelude behavior can be modified with attributes. The no_std
attribute
changes the prelude to the core prelude while the no_implicit_prelude
prevents the prelude from being added to the module.
The compiler comes with a default test framework. It works by attributing
functions with the test
attribute. These functions are only compiled when
compiling with the test harness. Like main, functions annotated with this
attribute must take no arguments, must not declare any
trait or lifetime bounds, must not have any [where clauses], and its return
type must be one of the following:
()
Result<(), E> where E: Error
Note: The implementation of which return types are allowed is determined by the unstable
Termination
trait.
Note: The test harness is ran by passing the
--test
argument torustc
or usingcargo test
.
Tests that return ()
pass as long as they terminate and do not panic. Tests
that return a Result
pass as long as they return Ok(())
. Tests that do not
terminate neither pass nor fail.
A function annotated with the test
attribute can also be annotated with the
ignore
attribute. The ignore
attribute tells the test harness to not
execute that function as a test. It will still only be compiled when compiling
with the test harness.
A function annotated with the test
attribute that returns ()
can also be
annotated with the should_panic
attribute. The should_panic
attribute
makes the test only pass if it actually panics.
The cfg
and cfg_attr
attributes control conditional compilation of items
and attributes. See the conditional compilation section for reference material
on these attributes.
A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation, for the static entity to which the attribute applies.
For any lint check C
:
allow(C)
overrides the check forC
so that violations will go unreported,deny(C)
signals an error after encountering a violation ofC
,forbid(C)
is the same asdeny(C)
, but also forbids changing the lint level afterwards,warn(C)
warns about violations ofC
but continues compilation.
The lint checks supported by the compiler can be found via rustc -W help
,
along with their default settings. Compiler
plugins can provide additional lint checks.
pub mod m1 {
// Missing documentation is ignored here
#[allow(missing_docs)]
pub fn undocumented_one() -> i32 { 1 }
// Missing documentation signals a warning here
#[warn(missing_docs)]
pub fn undocumented_too() -> i32 { 2 }
// Missing documentation signals an error here
#[deny(missing_docs)]
pub fn undocumented_end() -> i32 { 3 }
}
This example shows how one can use allow
and warn
to toggle a particular
check on and off:
#[warn(missing_docs)]
pub mod m2{
#[allow(missing_docs)]
pub mod nested {
// Missing documentation is ignored here
pub fn undocumented_one() -> i32 { 1 }
// Missing documentation signals a warning here,
// despite the allow above.
#[warn(missing_docs)]
pub fn undocumented_two() -> i32 { 2 }
}
// Missing documentation signals a warning here
pub fn undocumented_too() -> i32 { 3 }
}
This example shows how one can use forbid
to disallow uses of allow
for
that lint check:
#[forbid(missing_docs)]
pub mod m3 {
// Attempting to toggle warning signals an error here
#[allow(missing_docs)]
/// Returns 2.
pub fn undocumented_too() -> i32 { 2 }
}
Tool lints let you use scoped lints, to allow
, warn
, deny
or forbid
lints of
certain tools.
Currently clippy
is the only available lint tool.
They only get checked when the associated tool is active, so if you try to use an allow
attribute for a nonexistent tool lint, the compiler will not warn about the nonexistent lint until you use the tool.
Otherwise, they work just like regular lint attributes:
// set the entire `pedantic` clippy lint group to warn
#![warn(clippy::pedantic)]
// silence warnings from the `filter_map` clippy lint
#![allow(clippy::filter_map)]
fn main() {
// ...
}
// silence the `cmp_nan` clippy lint just for this function
#[allow(clippy::cmp_nan)]
fn foo() {
// ...
}
The must_use
attribute can be used on user-defined composite types
(struct
s, enum
s, and union
s) and functions.
When used on user-defined composite types, if the expression of an
expression statement has that type, then the unused_must_use
lint is
violated.
#[must_use]
struct MustUse {
// some fields
}
# impl MustUse {
# fn new() -> MustUse { MustUse {} }
# }
#
fn main() {
// Violates the `unused_must_use` lint.
MustUse::new();
}
When used on a function, if the expression of an
expression statement is a call expression to that function, then the
unused_must_use
lint is violated. The exceptions to this is if the return type
of the function is ()
, !
, or a zero-variant enum, in which case the
attribute does nothing.
#[must_use]
fn five() -> i32 { 5i32 }
fn main() {
// Violates the unused_must_use lint.
five();
}
When used on a function in a trait declaration, then the behavior also applies when the call expression is a function from an implementation of the trait.
trait Trait {
#[must_use]
fn use_me(&self) -> i32;
}
impl Trait for i32 {
fn use_me(&self) -> i32 { 0i32 }
}
fn main() {
// Violates the `unused_must_use` lint.
5i32.use_me();
}
When used on a function in an implementation, the attribute does nothing.
Note: Trivial no-op expressions containing the value will not violate the lint. Examples include wrapping the value in a type that does not implement
Drop
and then not using that type and being the final expression of a block expression that is not used.#[must_use] fn five() -> i32 { 5i32 } fn main() { // None of these violate the unused_must_use lint. (five(),); Some(five()); { five() }; if true { five() } else { 0i32 }; match true { _ => five() }; }
Note: It is idiomatic to use a let statement with a pattern of
_
when a must-used value is purposely discarded.#[must_use] fn five() -> i32 { 5i32 } fn main() { // Does not violate the unused_must_use lint. let _ = five(); }
The must_use
attribute may also include a message by using
#[must_use = "message"]
. The message will be given alongside the warning.
The cold
and inline
attributes give suggestions to the compiler to compile
your code in a way that may be faster than what it would do without the hint.
The attributes are only suggestions, and the compiler may choose to ignore it.
Both attributes can be used on closures, functions and function prototypes, although they do not do anything on function prototypes. When applied to a function in a trait, they apply only to that function when used as a default function for a trait implementation and not to all trait implementations.
The inline
attribute suggests to the compiler that it should place a copy of
the attributed function in the caller, rather than generating code to call the
function where it is defined.
Note: The compiler automatically inlines functions based on internal heuristics. Incorrectly inlining functions can actually make the program slower, so this attribute should be used with care.
There are three ways of using the inline attribute:
#[inline]
hints the compiler to perform an inline expansion.#[inline(always)]
asks the compiler to always perform an inline expansion.#[inline(never)]
asks the compiler to never perform an inline expansion.
The cold
attribute suggests to the compiler that the attributed function or
closure is unlikely to be called.
The derive
attribute allows certain traits to be automatically implemented
for data structures. For example, the following will create an impl
for the
PartialEq
and Clone
traits for Foo
, and the type parameter T
will be given
the PartialEq
or Clone
constraints for the appropriate impl
:
#[derive(PartialEq, Clone)]
struct Foo<T> {
a: i32,
b: T,
}
The generated impl
for PartialEq
is equivalent to
# struct Foo<T> { a: i32, b: T }
impl<T: PartialEq> PartialEq for Foo<T> {
fn eq(&self, other: &Foo<T>) -> bool {
self.a == other.a && self.b == other.b
}
fn ne(&self, other: &Foo<T>) -> bool {
self.a != other.a || self.b != other.b
}
}
You can implement derive
for your own traits through procedural macros.
The compiler may allow attributes for external tools where each tool resides in its own namespace. The first segment of the attribute path is the name of the tool, with one or more additional segments whose interpretation is up to the tool.
When a tool is not in use, the tool's attributes are accepted without a warning. When the tool is in use, the tool is responsible for processing and interpretation of its attributes.
Tool attributes are not available if the no_implicit_prelude
attribute is
used.
// Tells the rustfmt tool to not format the following element.
#[rustfmt::skip]
struct S {
}
// Controls the "cyclomatic complexity" threshold for the clippy tool.
#[clippy::cyclomatic_complexity = "100"]
pub fn f() {}
Note:
rustc
currently recognizes the tools "clippy" and "rustfmt".