I'm trying to determine if
let vector = std::mem::transmute::<Vec<NonZeroU8>, Vec<u8>>(vector); is OK or do I need
The documentation on this exists, but it's confusing. https://doc.rust-lang.org/std/mem/fn.transmute.html#alternatives has an example with a Vec being transmuted and claims it's UB, but doesn't explain why. I also don't understand why
.clone() is called on the vector being transmuted, yet the comments claim that the operation does not copy the vector.
Also the mem::forget at the end looks fishy. I think it should be before the transmute, not after.
That code block contains three completely separate ways to perform the type punning. The mem::forget at the end goes with the
from_raw_parts only. But it's true that the first (transmute) example shouldn't clone. (But either way it wouldn't need a
mem::forget, since transmute is by-value.)
As for why the transmute is UB, the simple reason is that
Vec doesn't guarantee that such type punning is OK. There's also the fact that we don't guarantee any kind of determinism for layout of repr(Rust) structs (of which
Vec is one), but for a stdlib type that's a technicality we could side-step if we wanted to.
.as_mut_ptr() does not consume the vector, merely returns a pointer, so when we call
.from_raw_parts() in that example we actually have mutable aliasing, which I believe is UB
I've run the first pattern through Clippy and it didn't complain, so I'll open an issue for Clippy as soon as this is clarified
Hmm, I would have said it's fine since the original Vec isn't used afterwards but it actually is, since it's passed to
For some reason miri doesn't complain about this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87a6f1f8bc386f3c80b5f6157da1b161
presumably because Vec just (transitively) contains a
Unique which is currently implemented as just a plain old raw pointer for aliasing questions
So that's a bug in miri?
I wouldn't say that, miri is making the most of what's in the liballoc source code. It's kind of a liballoc/rustc issue in that
Vec's data pointer doesn't get any noalias superpowers in LLVM IR generation either, but some other factors block that too, so I guess miri is the main way that this can be observed today
OK, I've opened an issue about the confusing docs: https://github.com/rust-lang/rust/issues/64073
I'd say it is a Miri limitation, I'd like to make
Unique meaningful eventually
but so far I did not have a good idea for how to do that