-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 incorrectly warns about struct fields that aren't dead due to transmuting #15102
Comments
You could rename the phantom fields such that they start with an underscore, then the lint will ignore them (much like the unused variable lint ignores variables starting with underscores). |
@jakub- Yeah I discovered that after filing this issue, and that's what I ended up doing, although I am not terribly happy about having my 3 struct definitions now actually differ. In any case, my basic point here is the |
@kballard Right, I agree that the lint's wording seems to imply it being precise (or conservative at the very least) rather than overly pessimistic, which it is now. I'm not sure if the solution to that is to make the lint even more complicated or simply changing the wording to reflect its nature. I find this lint useful but if the noise/signal ratio has turned out to be too high, then maybe it shouldn't be on by default. |
I'm obviously biased, but I think it should be kept enabled by default. The dead-code lint has these two utilities:
I believe the second part is much more useful. From my experience, it's a relief to have the lint warn you that the code you spent the whole day writing is dead because you forget to call that one function. Disabling the lint makes the second utility nonexistent. By the time you think of turning it on you probably have already figured out the problem. Yes, the lint was written to be conservative so the user can be confident that they may remove the code (the lint went through a lot of bug fix at the beginning to address that concern). If the noise/signal ratio becomes too high and no good solution can be found, I would prefer that dead items and dead fields be classified differently and keep the warning for the former on by default. |
False positives in on-by-default compiler warnings are terrible and will only cause people to disable useful warnings. Clang has taken an approach of limiting false positives and it has been quite successful. |
@ktt3ja I agree that the And it's for this reason that I think that the lint needs to try to learn about things like |
There's no guarantee they have identical layout, not at the moment anyway. The only way to ensure this (and the only correct way to transmute between different structs, IMO) is to fix the layout with An approach for your code would be to define struct StateLayout { L: *mut raw::lua_State, stackspace: i32 }
pub struct State { data: StateLayout }
pub struct ExternState<'a> { data: StateLayout }
pub struct RawState<'a> { data: StateLayout } and then you can even avoid transmutes when converting between the types. (Also, don't you need a ContravariantLifetime for |
@huonw Well, when the code was written, RFC 18 did not exist, so at the time they did in fact have a guarantee of identical layout. You're right in that, today, technically there's no guarantee, but the problem is also still purely theoretical, and practically speaking, if the compiler does start reordering structs, it will almost certainly reorder identically-defined structs into the same layout (yes I know there were examples of using randomized layout, but I would be surprised if that was ever made default behavior). In any case, given that structs no longer guarantee fixed layout, you are right to point out that my two major sources of concern ( As for |
@huonw Also, I think you're right, I should be using |
Triage: here's a test case for the transmute issue:
This does in fact warn about |
An other case where |
Triaging: The following test case still warns on #[derive(Debug)]
struct Foo {
x: i32,
}
struct Bar {
y: i32,
}
fn main() {
let bar = Bar{ y: 4 };
let foo: Foo = unsafe { std::mem::transmute(bar) };
format!("{:?}", foo);
} Adding |
As far as I can tell, the only remaining problem is that dead_code warns on fields that are used through transmute. However, |
Remove markdown injection for block comments Closes rust-lang/rust-analyzer#15091 I tried making it work but it doesn't seem possible, as the `*` of the closing `*/` sequence gets eaten by the markdown grammar no matter what.
The
dead_code
lint was recently (#14696) modified to detect dead struct fields. Unfortunately, it warns about fields even when it can't be 100% certain they're dead.One case where this happens was filed as #15101, where the struct is used as C FFI. That case has the (undocumented) solution of using
#[repr(C)]
(even though#[repr(C)]
hasn't been implemented to actually do anything yet).Another case that doesn't have a clear solution beyond turning off the warning is a struct that contains fields for the purpose of being memory-layout-compatible with another struct.
Notably, in lilyball/rust-lua@be46e268c0, the file
lib.rs
defines 3 structs with identical layout. Two of the structs properly use all defined fields, but one of the structs does not use one field (beyond initialization). However, there are methods that usemen::transmute()
to convert between the struct types. If this method is used, then the allegedly-dead field becomes live, as the destination struct uses that field.I recognize that this is a bit of an edge case, but this isn't the only one. Besides C FFI, a quick test demonstrates that a supposedly-unused struct field that is in fact printed via a
format!("{:?}", foo)
directive is also considered dead. I wouldn't be surprised to find out that there are more edge cases either. The basic point here is that thedead_code
lint is making an unqualified statement that the field is never used, but it doesn't actually have 100% certainty of that fact. It should be modified to recognize cases where the struct is used in ways the lint can't see into. So far the list of cases includes:*mut
to a C FFI functionmem::transmute()
::debug::fmt::secret_poly
And we can probably add casting
*mut StructType
to any*mut T
(viaas
, e.g.foo as *mut ()
) to the list./cc @jakub-
The text was updated successfully, but these errors were encountered: