-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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 lint wrongly warns about public repr(C) structs with private fields but no constructors #126169
Comments
Personally speaking I find this argument quite weak because the private field For example, the author of |
@fmease I would agree with all of that if this were all pure Rust code. But it isn't. libc has to represent structs that were defined in C, where zero-initialization is normal. Many of them already have fields used for padding, and the official C documentation requires zero-initialization. Can we please at least use a new name for this lint? Another case is when the only way to initialize a struct is to first allocate it uninitialized, and then populate it with a C library function or a syscall. To declare such a structure in pure safe Rust, the syscall which initializes it would have to be its constructor. But defining Rusty wrappers for such syscalls is beyond the scope of the libc crate, which is only concerned with structs and function definitions. |
kinda thought the dead code group had an unused field sublint already. |
The given reproducer is insufficient, compiling literally just this code in a library crate: pub struct Foo {
pub i: i16,
align: i16
} has been producing warnings for years. I don't know what's different about the libc crate, but the bisection using the entire libc crate is pretty easy and points to #125572. |
Ah! The difference is that the libc crate contains a zillion trait impls that aren't derived. This is a minimal reproducer: pub struct Foo(i16);
impl Clone for Foo {
fn clone(&self) -> Self {
Self(self.0)
}
} The change was that trait impls don't make the struct live anymore.
|
Ah! Here's a better reproducer: #[repr(C)]
pub struct Foo(i16); I don't know enough about the lint parts of the compiler to see how the diff in the regressing PR caused |
Right, I was going by |
For variables we have a way of making them "intentionally unused", IMO something similar would make sense here. If you rename the field to IMO we should keep warning for the code as-is. That field is unused, and only in unusual situations does it matter anyway, libc is one of these unusual situations. |
Oh, I think this is an issue about unconstructed pub structs, like the warnings in the build failure in the downstream issue. For unused fields, we can just underline them. But for pub structs which don't provide pub constructors, adding a new lint to control dead code analysis on pub structs may be a solution. IMO, adding pub constructors to these pub types or making all fields public is also an acceptable solution. |
Adding allow(unused) to such structs is also a reasonable option IMO. "The type is constructed exclusively by mem::zeroed" is a pretty unusual scenario, I am not convinced it is worth designing our lints around that.
|
Would you call "the type is constructed exclusively by FFI" a pretty unusual scenario? |
Certainly less so. However, I'd expect FFI types to have all-pub fields since presumably, the same definition exists in C, where there is no such thing as a private field. It is hardly accurate to say that a field is private when, in fact, code written outside the module -- in a different language even -- can construct values of this type with arbitrary field contents. |
I, for one, like the fact that you can relieve yourself from arbitrary rust code using the crate being able to break those values by using private fields. |
Arbitrary C code can break those values, so what's the point of preventing Rust code from doing so? |
If you go there, arbitrary Rust code can break those values too, even with private fields. But the thing is the code on the other side of FFI is not necessarily arbitrary either. And it could also be C++, which has private fields, too. |
There's a big difference between code that uses raw pointer hacks to bypass privacy, and writing a type in the expectation that the fields are initialized by code outside this module (even if that code is C++ and has private fields there, it is still outside the current module). When that is the expectation, then making the field private is IMO misleading - it sets an expectation of encapsulation that is not actually upheld by the system.
|
it'd be nice if all these unused field/variant/whatever lints had their own lint so when we want to allow them in a crate because we are pervasively doing that we can just... do that. |
|
There are many thousands of public |
Given the discussion above, what is the reason for having private fields in these types? To reiterate: the point of field privacy in Rust is to allow local reasoning. All code reading or writing those fields must be inside the current module. If you expect the struct to be constructed outside the module (e.g. by the OS), clearly that is not the case, so it seems that private fields don't serve much of a purpose? |
Whether or not this is desirable, this is a big expansion of the |
This approach provides an ideal abstraction to model the type-safety and semantic guarantees offered by certain Windows APIs and goes beyond that which can naturally be modeled in the Rust language. Using public fields would make these APIs substantially more dangerous to use since they could very easily be initialized incorrectly. |
So the argument is, the field really is private to the Windows OS, ideally not even the Rust module declaring them would have access? Maybe we need an |
Externally constructed is a good way to think about it, but ideally we could just get |
Update: the libc crate has also opted to silence these warnings. |
|
Interestingly, I found some code that technically does an exception for rust/compiler/rustc_passes/src/dead.rs Line 465 in 89a0cfe
|
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc `@NobodyXu` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting `@mu001999's` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc `@mu001999` r? `@pnkfelix` Fixes rust-lang#128272 Fixes rust-lang#126169
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc `@NobodyXu` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting `@mu001999's` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc `@mu001999` r? `@pnkfelix` Fixes rust-lang#128272 Fixes rust-lang#126169
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc `@NobodyXu` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting `@mu001999's` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc `@mu001999` r? `@pnkfelix` Fixes rust-lang#128272 Fixes rust-lang#126169
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc ``@NobodyXu`` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting ``@mu001999's`` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc ``@mu001999`` r? ``@pnkfelix`` Fixes rust-lang#128272 Fixes rust-lang#126169
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc ```@NobodyXu``` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting ```@mu001999's``` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc ```@mu001999``` r? ```@pnkfelix``` Fixes rust-lang#128272 Fixes rust-lang#126169
…hanges, r=pnkfelix Revert recent changes to dead code analysis This is a revert to recent changes to dead code analysis, namely: * efdf219 Rollup merge of rust-lang#128104 - mu001999-contrib:fix/128053, r=petrochenkov * a70dc29 Rollup merge of rust-lang#127017 - mu001999-contrib:dead/enhance, r=pnkfelix * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix There is an additional change stacked on top, which suppresses false-negatives that were masked by this work. I believe the functions that are touched in that code are legitimately unused functions and the types are not reachable since this `AnonPipe` type is not publically reachable -- please correct me if I'm wrong cc ````@NobodyXu```` who added these in #rust-lang#127153. Some of these reverts (rust-lang#126315 and rust-lang#126618) are only included because it makes the revert apply cleanly, and I think these changes were only done to fix follow-ups from the other PRs? I apologize for the size of the PR and the churn that it has on the codebase (and for reverting ````@mu001999's```` work here), but I'm putting this PR up because I am concerned that we're making ad-hoc changes to fix bugs that are fallout of these PRs, and I'd like to see these changes reimplemented in a way that's more separable from the existing dead code pass. I am happy to review any code to reapply these changes in a more separable way. cc ````@mu001999```` r? ````@pnkfelix```` Fixes rust-lang#128272 Fixes rust-lang#126169
Code
Current output
Desired output
Rationale and extra context
This warning is probably triggering because there's no constructor that allows a user to set the
align
field on structFoo
. However, there is still a valid way for a user to construct it:std::mem::zeroed()
. The libc crate contains many structs that must be initialized that way. libc could silence these warnings by#[allow(dead_code)]
, but that's too broad a brush. It would silence many much more serious warnings. Could we please either revert to the previous behavior, or else create a new lint for this that can be separately silenced?Other cases
No response
Rust Version
Anything else?
This is a regression since
rustc 1.80.0-nightly (f67a1acc0 2024-06-01)
. That version did not warn in such cases.Downstream issue: rust-lang/libc#3740
The text was updated successfully, but these errors were encountered: