#[derive(Debug)] field emits dead_code even if it's debug printed

fn main() {
    println!("{:?}", A { a: () });
    println!("{:?}", B { b: () }.b)
}

#[derive(Debug)]
struct A {
    a: (),
}

#[derive(Debug)]
struct B {
    b: (),
}

(Playground)

Output:

A { a: () }
()

Errors:

   Compiling playground v0.0.1 (/playground)
warning: field `a` is never read
 --> src/main.rs:8:5
  |
7 | struct A {
  |        - field in this struct
8 |     a: (),
  |     ^
  |
  = note: `A` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
  = note: `#[warn(dead_code)]` on by default

warning: `playground` (bin "playground") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.29s
     Running `target/debug/playground`

I have #[derive(Debug, Deserialize)] struct which is only used as debug print. Since its field is only being used in bail! and println!, the compiler warns about the field being not used.
Is this intended behavior? Should I just add #[expect(dead_code)] for these kind of fields that are only used for logging purpose?

Yes, #[derive(Debug)] is treated special by the dead_code lint. (This is also stated in the warning, btw.)

I would add #[allow(dead_code)] to the struct, yes. Maybe add a comment that explains why dead_code is disabled.

2 Likes

The reason that Debug is treated specially is that if it wasn't, since Debug should be implemented for almost every type, you would almost never get any warnings about unused fields at all.

1 Like