Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dead_code suggestion would break the semantics of code using#[repr(transparent)] #119659

Closed
tamird opened this issue Jan 6, 2024 · 8 comments · Fixed by #120107
Closed

dead_code suggestion would break the semantics of code using#[repr(transparent)] #119659

tamird opened this issue Jan 6, 2024 · 8 comments · Fixed by #120107
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. P-high High priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Milestone

Comments

@tamird
Copy link
Contributor

tamird commented Jan 6, 2024

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
    // `const`s 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

@tamird tamird added the C-bug Category: This is a bug. label Jan 6, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 6, 2024
tamird added a commit to tamird/aya that referenced this issue Jan 6, 2024
```
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(());
    |                      ~~
```

See rust-lang/rust#119659.
@shepmaster
Copy link
Member

Yes, the standard library had something similar and we allowed the warning:

#[repr(transparent)]
#[allow(dead_code)] // Field only used through `WithHeader` type above.
struct WithOpaqueHeader(NonNull<u8>);

Note that this isn't actually new, just recently applied to tuple struct fields. If you had used a named field:

#[repr(transparent)]
pub struct PrintkArg {
    z: u64,
}

You'd get less of a suggestion:

warning: field `z` is never read
 --> src/lib.rs:2:24
  |
2 | pub struct PrintkArg { z: u64 }
  |            ---------   ^
  |            |
  |            field in this struct
  |
  = note: `#[warn(dead_code)]` on by default

In #119645 we are discussing improvements to the lint message.

My own opinion is that the combination of #[repr(transparent)] and never reading the field is such a niche case that I don't expect that the diagnostic suggestion should mention it at all. Perhaps the lint documentation could.

@shepmaster shepmaster changed the title dead_code false positive in the presence of #[repr(transparent)] dead_code suggestion would break the semantics of code using#[repr(transparent)] Jan 6, 2024
@shepmaster
Copy link
Member

Of note is that #[repr(C)] appears to disable the warning here. That may be evidence towards doing the same for repr(transparent).

@saethlin saethlin added A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jan 6, 2024
@chorman0773
Copy link
Contributor

Since repr(transparent) means you can either transmute to the field or use it on an ABI boundary, I'd call the dead_code lint on it a false positive.

We had the same issue pop up in lccc for a type with a single ignored field that exists for a padding byte so that the definition can be matched in pre-C++20 code.

@traviscross
Copy link
Contributor

@rustbot labels +T-lang +I-lang-nominated

Nominating so we can answer the question, "should we suppress this lint for #[repr(transparent)] as we do for #[repr(C)], for both field and tuple structs?"

@rustbot rustbot added I-lang-nominated Nominated for discussion during a lang team meeting. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jan 8, 2024
@asquared31415
Copy link
Contributor

asquared31415 commented Jan 8, 2024

I think there's some utility in having users allow (or even expect) dead_code on a transparent struct that is only accessed indirectly. It documents the purpose of the code better. While this is a style concern rather than a semantics concern, I think that it is worth considering.

However it is weird that transparent and C aren't the same. I think that the decision should be made for both explicit reprs simultaneously.

@joshtriplett
Copy link
Member

We talked about this in today's @rust-lang/lang meeting. We agreed that we should treat repr(transparent) like repr(C) in this regard.

@traviscross
Copy link
Contributor

@rustbot labels -I-lang-nominated

As Josh said, there was a clear consensus to do this. Let's unnominate.

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label Jan 10, 2024
@compiler-errors compiler-errors added the regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. label Jan 17, 2024
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jan 17, 2024
@compiler-errors
Copy link
Member

I'm assigning this P-high because we definitely should fix it since it may inadvertently affect unsafe code via the transparent repr.

@compiler-errors compiler-errors added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 17, 2024
@Mark-Simulacrum Mark-Simulacrum added this to the 1.77.0 milestone Jan 17, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jan 19, 2024
…ent, r=Nilstrieb

dead_code treats #[repr(transparent)] the same as #[repr(C)]

In rust-lang#92972 we enabled linting on unused fields in tuple structs. In rust-lang#118297 that lint was enabled by default. That exposed issues like rust-lang#119659, where the fields of a struct marked `#[repr(transparent)]` were reported by the `dead_code` lint. The language team [decided](rust-lang#119659 (comment)) that the lint should treat `repr(transparent)` the same as `#[repr(C)]`.

Fixes rust-lang#119659
@bors bors closed this as completed in d95d6ce Jan 19, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jan 19, 2024
Rollup merge of rust-lang#120107 - shepmaster:dead-code-repr-transparent, r=Nilstrieb

dead_code treats #[repr(transparent)] the same as #[repr(C)]

In rust-lang#92972 we enabled linting on unused fields in tuple structs. In rust-lang#118297 that lint was enabled by default. That exposed issues like rust-lang#119659, where the fields of a struct marked `#[repr(transparent)]` were reported by the `dead_code` lint. The language team [decided](rust-lang#119659 (comment)) that the lint should treat `repr(transparent)` the same as `#[repr(C)]`.

Fixes rust-lang#119659
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Jan 21, 2024
…lstrieb

dead_code treats #[repr(transparent)] the same as #[repr(C)]

In #92972 we enabled linting on unused fields in tuple structs. In #118297 that lint was enabled by default. That exposed issues like #119659, where the fields of a struct marked `#[repr(transparent)]` were reported by the `dead_code` lint. The language team [decided](rust-lang/rust#119659 (comment)) that the lint should treat `repr(transparent)` the same as `#[repr(C)]`.

Fixes #119659
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. P-high High priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants