std::mem::size_of::<Result<Vec<u64>, u64>>()
says that Result<Vec<u64>, u64>
has a size of 24 bytes. However, Vec<u64>
already has a size of 24 bytes. Result
is an Enum type which uses a tag to distinguish the type. How does Rust compile manage to get rid of the tag in this case?
It's called a niche optimization. It's possible because the pointer in Vec
is always non-null, and so a value of 0
there means that the result is an Err
.
2 Likes
Vec<u64>
contains (ptr, len, capacity)
where ptr
is non-null. So you can use nullptr
as magic tag.
fn main() {
dbg!(std::mem::size_of::<Vec<u64>>()); // 24
dbg!(std::mem::size_of::<Option<Vec<u64>>>()); // 24
dbg!(std::mem::size_of::<Option<Option<Vec<u64>>>>()); // 32
}
For detail, Vec<T>
contains a NonNull<T>
which is annotated with #[rustc_layout_scalar_valid_range_start(1)]
which enable the niche optimization.
1 Like
See also std::ptr::NonNull
and std::num::NonZeroUsize
, for example.
1 Like
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.