Closed as not planned
Closed as not planned
Description
For some reason the compiler treats some value cast to bytes via mem::transmute
as uninitialized memory in a const function context.
use static_assertions::assert_eq_size;
struct Buf<const N: usize> {
bytes: [u8; N],
cursor: usize,
}
impl<const N: usize> Buf<N> {
const fn new() -> Self {
Self {
bytes: [0u8; N],
cursor: 0,
}
}
const fn push_u32_slice(&mut self, slice: &[u32]) {
if self.bytes.len() - self.cursor < slice.len() {
panic!("exceeded capacity");
}
let mut i = 0;
while i < slice.len() {
let array = slice[i].to_le_bytes();
let mut j = 0;
while j < slice.len() {
self.bytes[self.cursor + i] = array[j];
j += 1;
}
i += 1;
}
self.cursor += slice.len();
}
}
#[repr(u8)]
enum Frame {
First(u16),
Second,
}
assert_eq_size!(Frame, u32);
impl Frame {
const fn cast_slice(slice: &[Frame]) -> &[u32] {
// SAFETY We know the slice is valid and casting to bytes should
// always be valid, even if repr(rust) isn't stable yet.
unsafe { std::mem::transmute(slice) }
}
}
const FRAMES: &[Frame] = &[Frame::First(8), Frame::Second];
const NB_BYTES: usize = FRAMES.len() * std::mem::size_of::<Frame>();
const SERIALIZED_FRAMES: [u8; NB_BYTES] = {
let mut buf = Buf::<NB_BYTES>::new();
let bytes = Frame::cast_slice(FRAMES);
buf.push_u32_slice(&bytes);
buf.bytes
};
Here's a link to the repo with this code.
Meta
rustc --version --verbose
:
rustc 1.83.0-nightly (52fd99839 2024-10-10)
binary: rustc
commit-hash: 52fd9983996d9fcfb719749838336be66dee68f9
commit-date: 2024-10-10
host: x86_64-unknown-linux-gnu
release: 1.83.0-nightly
LLVM version: 19.1.1
Error output
error[E0080]: evaluation of constant value failed
--> src/lib.rs:23:25
|
23 | let array = slice[i].to_le_bytes();
| ^^^^^^^^ accessing memory based on pointer with alignment 2, but alignment 4 is required
|
note: inside `Buf::<8>::push_u32_slice`
--> src/lib.rs:23:25
|
23 | let array = slice[i].to_le_bytes();
| ^^^^^^^^
note: inside `SERIALIZED_FRAMES`
--> src/lib.rs:56:5
|
56 | buf.push_u32_slice(&bytes);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0080`.
error: could not compile `const_uninit_bug` (lib) due to 1 previous error
Edit1: Updated example to cast to u32 before casting to bytes for clarity