dead_code suggestion would break the semantics of code using#[repr(transparent)] · Issue #119659 · rust-lang/rust (original) (raw)

This occurs in aya:
https://github.com/aya-rs/aya/blob/e1aefa4e87970553dc60549141b3b4cf883f4366/bpf/aya-bpf/src/helpers.rs#L734-L737

On a nightly that includes #118297 I get:

error: field `0` is never read
   --> bpf/aya-bpf/src/helpers.rs:737:22
    |
737 | pub struct PrintkArg(u64);
    |            --------- ^^^
    |            |
    |            field in this struct
    |
    = note: `PrintkArg` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
    = note: `-D dead-code` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(dead_code)]`
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
    |
737 | pub struct PrintkArg(());

In a strict sense the compiler is correct. That's because PrintkArg is used like so:

pub unsafe fn bpf_printk_impl<const FMT_LEN: usize, const NUM_ARGS: usize>( fmt: &[u8; FMT_LEN], args: &[PrintkArg; NUM_ARGS], ) -> i64 { // This function can't be wrapped in helpers.rs because it has variadic // arguments. We also can't turn the definitions in helpers.rs into // consts because MIRI believes casting arbitrary integers to function // pointers to be an error. let printk: unsafe extern "C" fn(fmt: *const c_char, fmt_size: u32, ...) -> c_long = mem::transmute(6usize);

let fmt_ptr = fmt.as_ptr() as *const c_char;
let fmt_size = fmt.len() as u32;

match NUM_ARGS {
    0 => printk(fmt_ptr, fmt_size),
    1 => printk(fmt_ptr, fmt_size, args[0]),
    2 => printk(fmt_ptr, fmt_size, args[0], args[1]),
    3 => printk(fmt_ptr, fmt_size, args[0], args[1], args[2]),
    _ => gen::bpf_trace_vprintk(fmt_ptr, fmt_size, args.as_ptr() as _, (NUM_ARGS * 8) as _),
}

}

Thus the compiler's suggestion would break the semantics of this code. Playground. /cc @shepmaster