#[automatically_derived]Attribute
Explanation
#[automatically_derived] is an attribute the compiler inserts for you
on every impl block generated by #[derive(...)] — you almost never
type it yourself. Its only purpose is to mark that impl block as
machine-generated rather than hand-written, so that lints and other
tooling can tell the two apart.
You can see it by expanding a derive with cargo expand: a struct
carrying #[derive(Debug)] expands to an ordinary impl Debug for ...
block, but with #[automatically_derived] silently attached above it —
code you never wrote and don't normally look at, unless you're inspecting
expanded macro output directly.
The practical effect is on lints, not on runtime behavior — the attribute
has no effect on how the impl works, only on how tools treat it. Some
Clippy lints deliberately skip or soften their check inside
#[automatically_derived] blocks, on the reasoning that flagging a
pattern the compiler itself generated (rather than one a human typed) is
rarely actionable — there's no line of your own code to go fix. This is
also why the attribute is legal to write by hand: a third-party
#[proc_macro_derive] that wants its generated impls to be treated the
same way the compiler's own derives are (by Clippy and similar tools)
can emit #[automatically_derived] on its own generated code too.
Usage examples
Recognizing the compiler-generated attribute in expanded output
#[derive(Debug)] // <- the compiler attaches #[automatically_derived] to the impl this generates
struct Point { x: f64, y: f64 }
// roughly what `cargo expand` shows was generated (never written by hand):
// #[automatically_derived]
// impl std::fmt::Debug for Point { ... }
Designing a public API
A crate that ships its own #[proc_macro_derive], mimicking the
compiler's built-in derives, should tag its own generated impl blocks
with #[automatically_derived] too — matching the convention lets
downstream lints treat the custom derive's output the same way they treat
Debug/Clone/PartialEq.
// inside a #[proc_macro_derive(Describe)] function's generated output:
let expanded = quote::quote! {
#[automatically_derived] // <- marks this impl as generated, matching the compiler's own derives
impl Describe for #name {
fn describe() -> &'static str {
stringify!(#name)
}
}
};
Without the attribute, a lint has no way to
distinguish a custom derive's generated code from something a human
typed by hand, and may flag it with suggestions that don't apply to
generated code — emitting #[automatically_derived] is how a
third-party derive macro opts into the same tooling treatment the
compiler's built-in derives already get.