Does `#[automatically_derived]` have meaning in user code?

Since Rust 1.27, #[automatically_derived] hasn't been marked as an unused attribute. Does writing it in user code have any impact? Is it a good idea to put #[automatically_derived] on decl-macro generated trait implementations?

#[automatically_derived] is added by the compiler to mark items emitted by #[derive(Trait)]. IIRC, this is used to change some of the default lint levels and may impact the unused code lint more directly... though I cannot find a reference for this nor experimentally show that this is the case; I don't recall any specific effect that #[automatically_derived] has, or I could test more directly.

TIL the attribute is stable. I always assumed it was an implementation detail.


Here's an example where the attribute has an effect. Removing the attribute results in a warning.

#![warn(single_use_lifetimes)]

trait Foo<'a> {}

#[automatically_derived]
impl<'a> Foo<'a> for u8 {}

(playground)

I haven't checked the compiler for an exhaustive list of lints affected by the attribute. I believe you have th requisite knowledge to do this if you care enough for that.

3 Likes

Hmm, I wonder what it's supposed to do.

I would have guessed suppress stylistic lints, but apparently it doesn't suppress unused_parens: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3e97a75bdf4e04ac1022569f38b03765

2 Likes

Yeah I could rg the rustc tree but I'm not that curious :stuck_out_tongue_winking_eye:


I bumped into the fact that clippy uses this attribute to lint when you derive PartialEq but manually impl Hash (or the other way around) as well.

Mostly I think the attribute is just generally whatever rustc needs it to be, and is only stable accidentally rather than deliberately. It might be worth it to define it as silencing style lints; derives often end up #[allow]ing some lints to avoid cluttering up callers when they have to do interesting things to get the desired behavior.

This is extra interesting when derives trigger new style lints (as now they have to allow unknown lints as well) and when they trigger allow-by-default lints that don't normally get seen. (I know I'm guilty of putting #[allow(warnings)] in the output of a gnarly derive...)

We also have the power to say it even overrides #![forbid], if we want ...

TL;DR: huh, this is stable.