-
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
Warn and eventually forbid transmute::<T, U> for T or U with unspecified (Rust) layout #50842
Comments
I’ll be picking at the implementation of this during the impl days. |
Couldn't code assert the layout compatibility of all fields with |
There is prior art for this lint in the Also, what about pointer casts? Last question, as monomorphization time errors are ugly: We could add a |
I don't think they have a lot of common ground, neither in concept (non-C types can still have defined layout) nor in implementation.
What about it? Do you want to lint for
Precisely to avoid monomorphization time errors, transmute already doesn't work on type parameters (or more precisely, on types whose size depends on a type parameter). |
Thanks for the answers this clarified some stuff.
How is |
For starters, the pointer cast itself doesn't do anything of note and is always well-defined (assuming T and U are Sized, at least). It can be very useful even without ever dereferencing the pointer (e.g., smuggling a Rust type through a C API that deals in It's true that you can build your own transmute-like horror out of pointer casts and other primitives, but pointer casts alone are much more tame and general and more frequently necessary -- in fact many uses of transmute are best replaced with simpler pointer casts! |
@rkruppe makes sense, you convinced me. |
Experiments have been done in #51294 and conclusions drawn. Sorted by impact, these are the "unspecified" layout types that are transmuted the most from or to in the crates ecosystem:
In the compiler/libstd the following transmutes are common:
Many of these are genuine mistakes users make when transmuting, some others are "technically" safe from the standpoint of the layout (e.g. identity transmutes or lifetime transmutes) but questionable in other ways. Note, that implementation of such check broke some 7k of the crates transitively. If it was a proper lint, the impact would be lesser, but still very widespread. |
Is there a single dependency breaking all those crates, or are those 7k crates using transmute incorrectly ? Also, what's the plan here? I'd rather have this as a warning that can be turned off, than have nothing. Ideally, maybe one day some of those crates will be fixed, and we can enable this as a hard error. |
We can also start by linting the less frequent cases. I am much more worried about people transmuting |
There is a considerable number of crates using transmute incorrectly. Majority of the 7k broken crates is, of course, due to them depending on crates that use transmute incorrectly. |
Once there is an allow by default compatibility lint, there could be an effort/wg/call for participation where people send pull requests to the crates with issues. |
So I have gone through dozens of the failures here and there, and AFAICT for most crates there is nothing to fix. The only reason they fail is because they are still stuck on some older version of It is pretty hard to interpret how much breakage this will cause from the performed crater runs because all builds fail once a dependency fails to build. It would be way more informative to disable the transmute lint while compiling dependencies. |
So here are some transmutes that are always safe:
|
One trouble with this lint is that there's really 2 reasons a transmute could be justified:
The first question overlaps with #72774, so code could be shared with improper_ctypes. We have a a bunch of types that definitely have well-defined layout (most primitives [but not all, e.g. wide pointers/references], arrays, The second question is mostly independent and captures cases like "types only differ in lifetime". Here we have very little guidance, even for seemingly simple things like replacing |
It is a fairly commonplace mistake to do a
transmute::<T, U>
forT
andU
which are not necessarily compatible, but happen to work at that some particular point in time. These transmutes either change in behaviour when the compiler is updated or stop compiling altogether (because the size of T and size of U are not the same anymore (see e.g. #50830)).The same way we error for mismatching sizes, we can also raise such an error (possibly disable-able by a
#[feature(very_fast_such_dangerous)]
) for types for which sizes may change over time with future compiler releases. Namely, this would prevent usingtransmute
on stable for anything that#[repr()]
attribute on top of the type declaration;If we did that already, the issue linked before would’ve failed, because none of the enums have a
#[repr]
attribute on top of them, making their layout unspecified and therefore not transmutable.The text was updated successfully, but these errors were encountered: