A surprising enum size optimization in the Rust compiler

https://news.ycombinator.com/rss Hits: 15
Summary

A surprising enum size optimization in the Rust compiler April 7, 2025 Enums are one of the most popular features in Rust. An enum is type whose value is one of a specified set of variants. /// Foo is either a 32-bit integer or character. enum Foo { Int(u32), Char(char), } Values of type Foo are either integers (e.g. the variant Foo::Int(3) with a payload of 3) or characters (e.g. the variant Foo::Char('A') with a payload of 'A'). If you think of structs as being the and combination of their fields, enums are the or combination of their variants. This post is about a surprising optimization that the Rust compiler performs on the memory representation of enum values in order to make their memory usage smaller (spoiler: it’s not the niche optimization). In general, keeping values small can result in faster programs because values get passed around in CPU registers and more values fit in single CPU cache lines. Generally the size of an enum is the size of the largest payload, plus some extra bytes for storing a tag that specifies which variant the value is. For the type Foo above, both variant payloads take up 4 bytes, and we need an additional byte at least for the tag. A requirement called “type alignment” (which I won’t get into) requires that Rust actually use 4 bytes for the tag. So the overall size of the type is 8 bytes: assert_eq!(std::mem::size_of::<Foo>(), 8); (All the code snippets can be run here in the Rust Playground.) For the rest of this article it will be useful and interesting to actually see the memory representation of various enum values. Here’s a function that prints the raw bytes representation of any Rust value: /// Print the memory representation of a value of a type T. fn print_memory_representation<T: std::fmt::Debug>(t: T) { print!("type={} value={t:?}: ", std::any::type_name::<T>()); let start = &t as *const _ as *const u8; for i in 0..std::mem::size_of::<T>() { print!("{:02x} ", unsafe {*start.offset(i as isize)}); } println!(); } (This fu...

First seen: 2025-04-10 15:44

Last seen: 2025-04-11 05:47