Diagnostic attributes
The following attributes are used for controlling or generating diagnostic messages during compilation.
Lint check attributes
A lint check names a potentially undesirable coding pattern, such as
unreachable code or omitted documentation. The lint attributes allow
,
expect
, warn
, deny
, and forbid
use the MetaListPaths syntax
to specify a list of lint names to change the lint level for the entity
to which the attribute applies.
For any lint check C
:
#[allow(C)]
overrides the check forC
so that violations will go unreported.#[expect(C)]
indicates that lintC
is expected to be emitted. The attribute will suppress the emission ofC
or issue a warning, if the expectation is unfulfilled.#[warn(C)]
warns about violations ofC
but continues compilation.#[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,
Note: The lint checks supported by
rustc
can be found viarustc -W help
, along with their default settings and are documented in the rustc book.
Lint attributes can override the level specified from a previous attribute, as long as the level does not attempt to change a forbidden lint. Previous attributes are those from a higher level in the syntax tree, or from a previous attribute on the same entity as listed in left-to-right source order.
This example shows how one can use allow
and warn
to toggle a particular
check on and off:
This example shows how one can use forbid
to disallow uses of allow
or
expect
for that lint check:
Note:
rustc
allows setting lint levels on the command-line, and also supports setting caps on the lints that are reported.
Lint Reasons
All lint attributes support an additional reason
parameter, to give context why
a certain attribute was added. This reason will be displayed as part of the lint
message if the lint is emitted at the defined level.
Here is another example, where the lint is allowed with a reason:
The #[expect]
attribute
The #[expect(C)]
attribute creates a lint expectation for lint C
. The
expectation will be fulfilled, if a #[warn(C)]
attribute at the same location
would result in a lint emission. If the expectation is unfulfilled, because
lint C
would not be emitted, the unfulfilled_lint_expectations
lint will
be emitted at the attribute.
fn main() {
// This `#[expect]` attribute creates a lint expectation, that the `unused_variables`
// lint would be emitted by the following statement. This expectation is
// unfulfilled, since the `question` variable is used by the `println!` macro.
// Therefore, the `unfulfilled_lint_expectations` lint will be emitted at the
// attribute.
#[expect(unused_variables)]
let question = "who lives in a pineapple under the sea?";
println!("{question}");
// This `#[expect]` attribute creates a lint expectation that will be fulfilled, since
// the `answer` variable is never used. The `unused_variables` lint, that would usually
// be emitted, is suppressed. No warning will be issued for the statement or attribute.
#[expect(unused_variables)]
let answer = "SpongeBob SquarePants!";
}
The lint expectation is only fulfilled by lint emissions which have been suppressed by
the expect
attribute. If the lint level is modified in the scope with other level
attributes like allow
or warn
, the lint emission will be handled accordingly and the
expectation will remain unfulfilled.
If the expect
attribute contains several lints, each one is expected separately. For a
lint group it’s enough if one lint inside the group has been emitted:
Note: The behavior of
#[expect(unfulfilled_lint_expectations)]
is currently defined to always generate theunfulfilled_lint_expectations
lint.
Lint groups
Lints may be organized into named groups so that the level of related lints can be adjusted together. Using a named group is equivalent to listing out the lints within that group.
There is a special group named “warnings” which includes all lints at the “warn” level. The “warnings” group ignores attribute order and applies to all lints that would otherwise warn within the entity.
Tool lint attributes
Tool lints allows using scoped lints, to allow
, warn
, deny
or forbid
lints of certain tools.
Tool lints only get checked when the associated tool is active. If a lint
attribute, such as allow
, references 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() {
// ...
}
Note:
rustc
currently recognizes the tool lints for “clippy” and “rustdoc”.
The deprecated
attribute
The deprecated
attribute marks an item as deprecated. rustc
will issue
warnings on usage of #[deprecated]
items. rustdoc
will show item
deprecation, including the since
version and note
, if available.
The deprecated
attribute has several forms:
deprecated
— Issues a generic message.deprecated = "message"
— Includes the given string in the deprecation message.- MetaListNameValueStr syntax with two optional fields:
since
— Specifies a version number when the item was deprecated.rustc
does not currently interpret the string, but external tools like Clippy may check the validity of the value.note
— Specifies a string that should be included in the deprecation message. This is typically used to provide an explanation about the deprecation and preferred alternatives.
The deprecated
attribute may be applied to any item, trait item, enum
variant, struct field, external block item, or macro definition. It
cannot be applied to trait implementation items. When applied to an item
containing other items, such as a module or implementation, all child
items inherit the deprecation attribute.
Here is an example:
The RFC contains motivations and more details.
The must_use
attribute
The must_use
attribute is used to issue a diagnostic warning when a value
is not “used”. It can be applied to user-defined composite types
(struct
s, enum
s, and union
s), functions,
and traits.
The must_use
attribute may include a message by using the
MetaNameValueStr syntax such as #[must_use = "example message"]
. The
message will be given alongside the warning.
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.
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.
When used on a trait declaration, a call expression of an expression
statement to a function that returns an impl trait or a dyn trait of that trait violates
the unused_must_use
lint.
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.
When used on a function in a trait 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.
Note: It is idiomatic to use a let statement with a pattern of
_
when a must-used value is purposely discarded.
The diagnostic
tool attribute namespace
The #[diagnostic]
attribute namespace is a home for attributes to influence compile-time error messages.
The hints provided by these attributes are not guaranteed to be used.
Unknown attributes in this namespace are accepted, though they may emit warnings for unused attributes.
Additionally, invalid inputs to known attributes will typically be a warning (see the attribute definitions for details).
This is meant to allow adding or discarding attributes and changing inputs in the future to allow changes without the need to keep the non-meaningful attributes or options working.
The diagnostic::on_unimplemented
attribute
The #[diagnostic::on_unimplemented]
attribute is a hint to the compiler to supplement the error message that would normally be generated in scenarios where a trait is required but not implemented on a type.
The attribute should be placed on a trait declaration, though it is not an error to be located in other positions.
The attribute uses the MetaListNameValueStr syntax to specify its inputs, though any malformed input to the attribute is not considered as an error to provide both forwards and backwards compatibility.
The following keys have the given meaning:
message
— The text for the top level error message.label
— The text for the label shown inline in the broken code in the error message.note
— Provides additional notes.
The note
option can appear several times, which results in several note messages being emitted.
If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value.
Any other occurrence generates an lint warning.
For any other non-existing option a lint-warning is generated.
All three options accept a string as an argument, interpreted using the same formatting as a std::fmt
string.
Format parameters with the given named parameter will be replaced with the following text:
{Self}
— The name of the type implementing the trait.{
GenericParameterName}
— The name of the generic argument’s type for the given generic parameter.
Any other format parameter will generate a warning, but will otherwise be included in the string as-is.
Invalid format strings may generate a warning, but are otherwise allowed, but may not display as intended. Format specifiers may generate a warning, but are otherwise ignored.
In this example:
#[diagnostic::on_unimplemented(
message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`",
label = "My Label",
note = "Note 1",
note = "Note 2"
)]
trait ImportantTrait<A> {}
fn use_my_trait(_: impl ImportantTrait<i32>) {}
fn main() {
use_my_trait(String::new());
}
the compiler may generate an error message which looks like this:
error[E0277]: My Message for `ImportantTrait<i32>` implemented for `String`
--> src/main.rs:14:18
|
14 | use_my_trait(String::new());
| ------------ ^^^^^^^^^^^^^ My Label
| |
| required by a bound introduced by this call
|
= help: the trait `ImportantTrait<i32>` is not implemented for `String`
= note: Note 1
= note: Note 2