-
Notifications
You must be signed in to change notification settings - Fork 13.3k
std::mem::transmute
may mutate result
#96140
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
Comments
std::mem::transmute
may mutate datastd::mem::transmute
may mutate result
The transmute has to produce a valid value. For a bool type there are only two valid values: 0 and 1. Anything else would result in an undefined behaviour. For example, when running linked playground code under Miri (available in Tools), Miri identifies the following issue:
|
@tmiasko To be honest, I am doubtful that |
Maybe the problem is LLVM just getting a bit confused because a bool value is actually |
It's undefined behavior for a boolean to have any values other than 1 or 0, so this is valid codegen on LLVM's part. When transmuting a
Undefined behavior is undefined behavior. The compiler can do whatever it wants to with this code, for all you know it could decide to explode if values other than zero or one are passed to the function. Yes, this can cause nasty bugs as UB is prone to do but that's a side effect of falling afoul of UB, not a compiler or backend bug of any sort. |
While it's valid codegen, it's missing optimization. The I disagree the |
It is not possible to tell if this code has Undefined Behavior or not without seeing the contents of Bar. But I don't think that's a bug -- that is just inherent in how |
Do you have an example of this use-case being a performance bottleneck in a sample program with practical effects that we can benchmark? LLVM insists any boolean value, in most practical cases, to interact with most of LLVM's instruction set that is intended to model "compare then act" in assembly, become an In fact, in a fully "worked" optimization of practical code, by making sure it can pretend this is only talking about single bits, LLVM may even happily choose to turn all this into flag-only operations, causing the byte in this conversation to vanish in a puff of logic. And the Rust abstract machine definitely has no idea what a "flags register" even is, in spite of generated x86 code using such. |
It doesn't -- for programs that do not have UB. For programs that have UB, no promises are made. Ever. That's how Passing any value other than 0 or 1 to your
|
Yea, the only actionable thing I can see here is to remove the extra asm instructions for perf reasons or to allow follow up optimizations to trigger. I guess let's close this and if someone encounters a repro for more complex programs that have missing opts we can revisit |
Example Code
During some experimenting in the Rust playground, I noticed something strange with the assembly output from
transmute
.Playground
Expected Output
transmute
should copy the input memory with no mutations. I expected this to put x in the return register and return:Actual Output
However the resulting value gets modified in the process producing the following output:
Now, I don't have any issue with the compiler choosing any arbitrary approach for representing a
bool
withinstd::mem::size_of::<bool>()
bytes. However, I was under the impression thatstd::mem::transmute
never mutates the underlying data. To quote the documentation, "It’s equivalent to C’smemcpy
under the hood, just liketransmute_copy
." At the moment it feels like this contract is not being upheld.Structs
However, the bigger issue is
transmute
may or may not apply this adjustment tobool
fields in structs. This could probably hide some nasty bugs that would be extremely hard to debug. Take for example the code below:(Playground with panic (small
Bar
)) (Playground no panic (largeBar
))It is not possible to tell if this code will panic without seeing the contents of
Bar
. The primary factors that determine if a panic occurs seems to be the size ofBar
and at when in the compilation processfrom_buffer
/to_buffer
are inlined. Smallstructs
with less fields are more likely to have theirbool
s adjusted. Depending on which function thetransmute
is in, the compiler may determine that thetransmute
s will cancel out and will not produce an error.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: