Rust has MaybeUninit<>
but reading truly uninit memory is UB
.
LLVM freeze
can eliminate it at a tiny performance cost.
Let's indulge into "can we" first and "should we" later
Yesterday I suggested
type mu8 = MaybeUninit<u8>;
and a coercion:
impl mu8 {
// applied automatically each time
// - mu8 is assigned to u8
// - mu8 is used in an expression like a + 1
fn freeze(self) -> u8 { /* LLVM freeze */ }
}
This makes reading mu8
safe and removes UB.
Less UB and less unsafe
is a win isn't it?
The idea is to stop using unsafe
facility offered by MaybeUninit
for reading mu8
entirely both in safe and unsafe
code.
Further steps to imagine
Apply said autocoercion to all (primitive?) types for which all bit patterns are valid.
Use mut mu8
for local variables as a sort of extreme optimization: say a loop is executes at least once, variable is never read inside the loop but is assigned; we don't really need to assign initial value.
Allow new safe syntax:
struct A {b : B}
let a : MaybeUninit<A> = ...
a.b // would be typed as MaybeUninit<B>
Most ambitious: grow typestate muscle/syntax to track which parts of a struct are uninit to allow gradual initialization.
Typestate-light: if the compiler can prove that at a certain point in control flow a local MaybeUninit
variable has been assigned to it treats it as having the "underlying" type from that point on.
Use &MaybeUninit
for out-only parameters (but somehow treat them as fully init afterwards using only safe code???...)
Introduce reverse autocoercion from u8
to mu8
and in other similar cases.
P.S. I'm aware of security implications but would like to discuss feasibility first. I'm also aware older LLVM versions supported by Rust don't provide freeze
.