{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreicptxoac5zrfbn2bp24gumhwb4yh6kog2ykiqtzn4x5g4z3numhly",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mh7rqi3blks2"
},
"path": "/t/maybeinvalid-t-separate-concepts-of-uninitialized-memory-and-invalid-values/24087#post_3",
"publishedAt": "2026-03-16T20:15:11.000Z",
"site": "https://internals.rust-lang.org",
"tags": [
"[1]",
"(click for more details)",
"↩︎"
],
"textContent": "I don’t think I’m fully understanding how this is supposed to make `freeze` any easier, but I’m also not quite getting the proposed type’s properties in the first place.\n\nNote that even for _valid_ types, uninitialized bytes are often an option. For example for a type like `MaybeUninit<u8>` itself; or for the padding bytes in a struct (if it has any padding bytes).\n\nIn my mental model, a value in Rust (only speaking of the shallow data, not data behind pointers) consists - basically - just of a sequence of bytes[1], but every _byte_ of memory has not only the 256 different values (from `0` to `255`) for concrete numerical values, but also an additional 256’th value that we can call “uninitialized”. (In LLVM this corresponds to the value “`undef`”.) In Rust types, a byte is thus represented by `MaybeUninit<u8>`.\n\nA struct or enum value, consisting of a (usually fixed-length) sequence of bytes usually then comes with additional _restrictions_ on the possible values of its bytes. These restrictions could be independent for each byte, but they can also interdepend.\n\nFor example `u8` is one byte, and restricted to not be `undef`.\n\nFor people worrying about `undef` not existing at run-time – that’s not really an issue in the abstract machine model. There it _really is_ an `undef` separate from all other possible values for a byte; just the rules that disallow you from “reading” `undef` (in a sense of trying to read it as any other concrete byte value `0` through `255`) mean that in lowering it into _concrete_ machine code, it never actually needs to be written or read at run-time.\n\nNow, `MaybeUninit<T>` lifts all the byte-level restrictions that the type `T` introduces on its (shallow) data. In this mental mode, `MaybeUninit` does nothing else but allow invalid values. Whether or not uninit byte values are allowed depends on the type – i.e. for certain `T` in certain bytes (and under perhaps certain conditions of what the _other_ bytes may be) undef is allowed or not allowed in plain `T`; of course it’s always allowed anywhere in `MaybeUninit<T>` because that allow all invalid values, too.\n\nBut now you propose `MaybeInvalid<T>` and write down that “non-fixed value” should still be disallowed (by “non-fixed” I suppose you’re referring to `undef` byte values?) And this doesn’t fit my mental model well, because `<T>` itself may have never rules some `undef` bytes. So I’d assume you might mean that it allows additional invalid values that aren’t undefined, but never adds additional undefined values?\n\nBut what are the _exact_ rules?\n\nSome example questions that precise rules will have to be able to give an answer for: (click for more details)\n\n* * *\n\n 1. ignoring additional information like provenance ↩︎\n\n 2. assuming straightforward, repr-`C`-like layout of the tuple! ↩︎\n\n\n",
"title": "`MaybeInvalid<T>` - separate concepts of uninitialized memory and invalid values"
}