Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should Option<u128> use a smaller (maybe usize) tag? #138332

Open
scottmcm opened this issue Mar 11, 2025 · 4 comments
Open

Should Option<u128> use a smaller (maybe usize) tag? #138332

scottmcm opened this issue Mar 11, 2025 · 4 comments
Labels
A-layout Area: Memory layout of types needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@scottmcm
Copy link
Member

Looking at some examples in #137278 (comment) shows that Option<u128> is using a full u128 for its stored tag. That tag, of course, can only be 0 or 1.

As a result things like returning Some(…) need to write two qwords on x64 into the return value, even though of course one of them is only ever all-zeroes.

Could we maybe give it a layout equivalent to (usize, u128) instead?

Or, in general, can we cap the size of tags to a native machine word, given a small discriminant that could fit in just about any type?

(Aside: It's good for Option<u32> to still be (u32, MaybeUninit<u32>), since that has more niches than (u8, MaybeUninit<u32>). But going so big that it takes multiple instructions to write the tag seems like overkill, and for unconstrained repr(Rust) we should probably stop at something reasonable for the target.)

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 11, 2025
@scottmcm scottmcm added A-layout Area: Memory layout of types needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 11, 2025
@lolbinarycat
Copy link
Contributor

Unfortunately, we're constrained by this line from the reference:

The size of a value is always a multiple of its alignment

@lolbinarycat lolbinarycat added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 13, 2025
@lolbinarycat
Copy link
Contributor

It might be possible to give Option a custom calling convention though, similar to how slices are passed as 2 arguments.

@hanna-kruppe
Copy link
Contributor

This wouldn’t change alignment, just (possibly) introduce padding in the memory layout, just like how moving (u8, u128) only needs to load/store 9 bytes despite the tuple being 8 + align_of::<u128>() bytes.

@scottmcm
Copy link
Member Author

scottmcm commented Mar 14, 2025

It might be possible to give Option a custom calling convention though

We already do that -- Option<u32> uses ScalarPair layout. (Even Option<u128> does, it's just a pair of u128 and MaybeUninit<u128>.)

As does (usize, std::mem::MaybeUninit<u128>) https://rust.godbolt.org/z/qGavbhvoo, so this is just a request to make Option<u128> use the same layout as that tuple.

(Sure, it won't make it smaller in memory on any platform where alignof(u128) is 16, but that's ok.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-layout Area: Memory layout of types needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants