{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreigayo675q55r4kv2ml6m5kstctgitrgfje42b764la4use3zfqk2i",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mh7rqs6kurl2"
},
"path": "/t/maybeinvalid-t-separate-concepts-of-uninitialized-memory-and-invalid-values/24087#post_1",
"publishedAt": "2026-03-16T19:16:06.000Z",
"site": "https://internals.rust-lang.org",
"tags": [
"17188",
"22254",
"13231"
],
"textContent": "Currently, uninitialized memory is dealt with using a `MaybeUninit<T>` type. But:\n\n 1. Unitialized memory is **difficult**\n 2. It can also store inproperly initialized values\n\n\n\nSo it might be better to dedicate `MaybeUninit` to the first point only and separate the second into a distinct type.\n\n## Idea\n\nCreate a new type that can store `T` without proper initialization, but unlike `MaybeUninit` it must contain a fixed value:\n\n| Valid value | Invalid value | Non-fixed value\n---|---|---|---\n`MaybeUninit<T>` | | |\n`MaybeInvalid<T>` | | |\n`T` | | |\n\n\n #[repr(transparent)]\n pub union MaybeInvalid<T> {\n invalid: (),\n value: ManuallyDrop<T>,\n }\n\n impl<T> MaybeInvalid<T> {\n ...\n // similar to MaybeUninit<T>\n }\n\n\n`MaybeUninit` would get new functions to interact with it:\n\n\n impl<T> MaybeUninit<T> {\n ...\n pub fn written(MaybeInvalid<T>) -> Self;\n pub unsafe fn assume_written(self) -> MaybeInvalid<T>;\n pub unsafe fn assume_written_ref(&self) -> &MaybeInvalid<T>;\n pub unsafe fn assume_written_mut(&mut self) -> &mut MaybeInvalid<T>;\n pub fn write_raw(&mut self, MaybeInvalid<T>) -> &mut MaybeInvalid<T>;\n }\n\n\n## Case 1: `enum` optimization\n\nWe could define a trait that gives a compiler \"an example\" of invalid value of this type:\n\n\n /// ## Safety\n /// INVALID's value must be actually invalid:\n /// impossible to obtain in safe Rust\n pub unsafe trait Invalid: Sized {\n const INVALID: MaybeInvalid<Self>;\n }\n\n // example\n unsafe impl<'a, T> Invalid for &'a T {\n const INVALID: MaybeInvalid<Self> = MaybeInvalid::zeroed();\n }\n\n\nThis could be used to optimize `enum`s layout for arbitrary user types:\n`for<T: Invalid> assert_eq!(size_of::<T>(), size_of::<Option<T>>)`\n\n## Case 2: `freeze`ing uninitialized values\n\nLLVM's `freeze` instruction, mentioned a couple of times (17188, 22254, 13231 from a quick search) here, would become trivial and safe:\n\n\n impl<T> MaybeUninit<T> {\n ...\n pub fn freeze(self) -> MaybeInvalid<T>;\n }\n\n\nAnd if we had some auto trait for always-valid types, then one could create an \"uninitialized\" buffer without using `unsafe`:\n\n\n let mut buf = MaybeUninit::<[u8; 256]>::uninit().freeze().valid();\n\n\nThat trait would be mutually exclusive with `Invalid` from case 1 though, which is probably fine - there are `Drop` and `Copy` but these are fundamental.",
"title": "`MaybeInvalid<T>` - separate concepts of uninitialized memory and invalid values"
}