You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rustc complains about unused code if item is used in #[automatically_derived] context #126031
I expected to see this happen: The code compiles without any warnings since, the Identity struct is clearly used.
Instead, this happened: The compiler emits a dead_code lint, telling me that the struct is never constructed
Example where this can occur: when using the derive_more crate to derive a specialized Debug implementation, and the usage of derive_more::Debug utilizes a formatter struct to avoid allocating into an intermediate heap allocated buffer
@apiraino After some investigation I don't think this is a regression. We can construct the following, which will also trigger dead_code lint in previous versions:
Before 1.78, dead code analysis will check all impls regardless of whether the struct is used or not, so that we don't see such warnings cause it has an impl block. In fact, the reason is that the impl Debug is not automatically derived, and we can't construct such cases with only using #[derive(Debug)].
@aumetra in the Real-world example, it's because #[debug("{}", BinaryToStringEncoder(msg))] introduces the user-defined approach to impl Debug.
I don't know which macro the #[debug("{}", BinaryToStringEncoder(msg))] belongs to, but I think one way to solve this is to not generate #[automatically_derived] if users add such #[debug(...)] on fields.
I don't know which macro the #[debug("{}", BinaryToStringEncoder(msg))] belongs to, but I think one way to solve this is to not generate #[automatically_derived] if users add such #[debug(...)] on fields.
It's actually part of derive_more, so a pretty abundant crate in the ecosystem. But I guess not a lot of people are hitting this issue because not a lot of people do something like this.
@aumetra furthermore, automatically_derived is helpful to lint never read fields by treating reading in the Debug impl as trivial reading:
#[derive(Debug)]structT(i32);fnmain(){let x = T(1);println!("{x:?}")}
so that we can still get field 0 is never read, cause it's only used in the derived impl Debug.
As a comparison, Identity in #126031 (comment) is also only constructed in the Debug impl, that's why we lint it like those fields only used for debugging.
I guess another way to solve this in the real-world example is to print differently when meeting different fmt::Formatter's config in impl Debug for Binary, and then use the specific fmt_str in the #[debug(...)] on fields to determine the behavior.
Refer to #126031 (comment), I will close this because the behavior is intentional to avoid linting items only used in automatically derived Debug impls.
Activity
aumetra commentedon Jun 5, 2024
Okay, I submitted it under the wrong category. Apologies for that. Clearly a diagnostic issue.
aumetra commentedon Jun 5, 2024
@rustbot modify labels: -regression-from-stable-to-stable +A-diagnostics
aumetra commentedon Jun 5, 2024
@rustbot modify labels: -I-prioritize +T-compiler
apiraino commentedon Jun 5, 2024
Actually I think you were right, seems to be a diagnostic regression introduced in c69fda7 (so my bisection reports):
cc @mu001999 since author of #121752 and @pnkfelix (reviewer of said patch)
@rustbot label +regression-from-stable-to-stable +P-medium -needs-triage
mu001999 commentedon Jun 5, 2024
@rustbot claim
mu001999 commentedon Jun 6, 2024
@apiraino After some investigation I don't think this is a regression. We can construct the following, which will also trigger
dead_codelint in previous versions:Before 1.78, dead code analysis will check all impls regardless of whether the struct is used or not, so that we don't see such warnings cause it has an impl block. In fact, the reason is that the
impl Debugis not automatically derived, and we can't construct such cases with only using#[derive(Debug)].@aumetra in the Real-world example, it's because
#[debug("{}", BinaryToStringEncoder(msg))]introduces the user-defined approach to implDebug.I don't know which macro the
#[debug("{}", BinaryToStringEncoder(msg))]belongs to, but I think one way to solve this is to not generate#[automatically_derived]if users add such#[debug(...)]on fields.aumetra commentedon Jun 6, 2024
It's actually part of
derive_more, so a pretty abundant crate in the ecosystem. But I guess not a lot of people are hitting this issue because not a lot of people do something like this.mu001999 commentedon Jun 7, 2024
@aumetra furthermore,
automatically_derivedis helpful to lint never read fields by treating reading in theDebugimpl as trivial reading:so that we can still get
field0is never read, cause it's only used in the derivedimpl Debug.As a comparison,
Identityin #126031 (comment) is also only constructed in theDebugimpl, that's why we lint it like those fields only used for debugging.I guess another way to solve this in the real-world example is to print differently when meeting different
fmt::Formatter's config inimpl Debug for Binary, and then use the specific fmt_str in the#[debug(...)]on fields to determine the behavior.mu001999 commentedon Jun 14, 2026
Refer to #126031 (comment), I will close this because the behavior is intentional to avoid linting items only used in automatically derived
Debugimpls.