{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreicqfmoo463eky2jfvsptq5fer6uhifbzlsts7dgxbwa2q37xkjcqq",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mkqlzihnfkp2"
},
"path": "/t/could-collections-hypothetically-store-keys-and-values-inline/24195#post_18",
"publishedAt": "2026-04-30T20:27:15.000Z",
"site": "https://internals.rust-lang.org",
"tags": [
"[1]",
"@Vorpal",
"How Swift Achieved Dynamic Linking Where Rust Couldn't - Faultlore",
"[2]",
"↩︎"
],
"textContent": "CAD97:\n\n> It is a form of it, yes. When you exceed the allocated inline space, all of the map is transferred to the heap. The Rust `enum` overlaps the `Heap` and `Inline` case, using an invalid value of one to mark when the other is in use so the size equals that of the larger variant.\n>\n> Because Rust is statically typed, types _must_ have a fixed stack size. `HashMap` is currently 6×`usize`. You'll be hard-pressed to fit more than one key/value pair in that space. If you have a use case where most of your maps only have one int-string entry... maybe you _shouldn't_ be using the general purpose stdlib `HashMap`.\n\nYes, sure, it is a form of optimization for small maps specifically. But it is not a direct analog of the \"small string optimization\" implemented by C++ and `compact_str`. It is a different way of optimizing for small maps by putting them on the stack[1] and so while you could reasonably call it a \"small map optimization\" in a vacuum, it is not the same thing and not what @Vorpal was originally referring to.\n\nThe direct analog is specifically storing things in those 6 `usize`-shaped values, which as you point out, wouldn't be very useful, which was my point.\n\nCAD97:\n\n> Because Rust is statically typed, types _must_ have a fixed stack size.\n\nAlso, this is further besides the point, but static typing has little to do with requiring types to have a fixed size on the stack. The only major language I'm aware of opting out of fixed-sized types on the stack as a matter of policy is Swift, which is statically typed and uses `alloca` heavily in its implementation of dynamically-linked generic types and such (How Swift Achieved Dynamic Linking Where Rust Couldn't - Faultlore is a very cool article on the topic, for anyone unfamiliar).\n\nI think it's reasonable that Rust defaults to the position that everything must have a static stack size,[2] but it's not a fundamental property of static typing, nor does dynamic typing make it easier.\n\n* * *\n\n 1. It doesn't seem like a particularly good implementation either—if your hash map is 16 items you should probably be doing linear search over an array. It also includes a 48 byte overhead over storing key-value pairs in an array and doing linear search, which seems fairly significant if you're optimizing for the case of small maps. ↩︎\n\n 2. Though maybe having more support for dynamically-sized objects would be a benefit to the language. It would be nice to be able to place dynamically-sized objects on the stack and to be able to express things like `dyn<T: Trait> Vec<T>` where all the elements have the same underlying type (and thus stride) and so you can store them contiguously, only storing their vtable pointer once with the `Vec` and avoiding a bunch of unnecessary allocations, compared to something like `Vec<Box<dyn T>>`. ↩︎\n\n\n",
"title": "Could collections hypothetically store keys and values inline?"
}