I am building a Vec type that works in a const context, with a fixed maximum capacity.
I want to convert the vector to a &'static [T]
using constant promotion when I'm finished editing it.
This is what I came up with:
pub struct ConstVec<const CAP: usize, T> {
arr: [MaybeUninit<T>; CAP],
len: usize,
}
impl<const CAP: usize, T> ConstVec<CAP, T> {
pub const fn new() -> Self {
Self {
arr: [const { MaybeUninit::uninit() }; CAP],
len: 0,
}
}
// ... snip ...
// Problematic function
pub const fn into_slice(self) -> &'static [T] {
unsafe {
let ptr = self.arr.as_ptr() as *const T;
core::slice::from_raw_parts(ptr, self.len)
}
}
}
This code compiles without problems, but when I try to use it:
const fn make_vec<const CAP: usize>() -> ConstVec<CAP, usize> {
let mut vec = ConstVec::new();
let mut index = 0;
while index < CAP {
vec.push(index);
index += 1;
}
vec
}
// error[E0080]: it is undefined behavior to use this value
const VALUE: &[usize] = make_vector::<10>().into_slice();
I get this error:
error[E0080]: it is undefined behavior to use this value
--> src/lib.rs:180:5
|
180 | const VALUE: &[usize] = make_vector::<10>().into_slice();
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it
should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
βΎββββalloc61<imm>ββββββΌ 0a 00 00 00 00 00 00 00 β βΎβββββββΌ........
}
The compiler tells me that there is a dangling reference.
Is it caused by the fact that the underlying array is dropped?
Is there a way to fix this error?