rust-lang/rust

Tracking issue for feature(repr128); enums with 128-bit discriminants

Centril opened this issue · 8 comments

This issue tracks repr128, i.e. "enums with 128-bit discriminant" as per rust-lang/rfcs#1504.
Originally this was tracked in #35118.


Nothing has changed re repr128… It is still the case that at least LLVM’s debuginfo API blocks us from implementing it at all. There’s very little incentive to work on it, though, and I’m not planning to do anything in that direction until a very convincing use-case for 128-bit enum discriminants comes up.

- @nagisa

I actually double checked the RFC text and I didn't see mentions of repr(u128) anywhere. Is it still a feature that's desired?

It’s a generic feature tied to integers in the language. It is not mentioned in the RFC because it would’ve implemented along with the integers themselves lest the roadblocks didn’t show up.

Is there any progress on this?

My use-case is that I often use #[repr(uXXX)] on enums with the enumflags2 crate in order to be able to manage set of values packed in an integer. That is very handy to avoid using a BTreeSet (heap allocation etc) but as soon as you have more then 64 different values (and less than 128 obviously), you would want to use #[repr(u128)] in stable but that's not currently possible.

I don't know if that's enough of a convincing use-case but that would be really handy to have this working in stable.

Is there any path forward that I could help with? Is LLVM debuginfo API still a blocker?

I believe there hasn't been any progress on this since the original comment.

I have a use-case also, using an enum to represent fixed amount denominations for a cryptocurrency in development. u128 is necessary/desirable to have enough divisibility.

presently I am working around by defining the variants as a list (without integer values) and then using giant match statements to convert to/from. works, but is ugly.

I mean, u64 allows up to 10^19, so I'm not sure what kinds of quantities you need to include. If we translate that into metric prefixes, that'd be all the way to exa (10^18).

yes, well in fact we may use u64 in the end, but there has been discussion/debate around using u128 for greater divisibility, so our prototype code can build either way via a type alias. Unfortunately trying to use repr(u128) fails to compile, hence the workaround.

There are other ways we could represent this. We don't have to use an enum at all. It is simply the data structure that seems most suited to the task, so I was (a bit) surprised to find that u128 doesn't work the same as other integer types. Symmetry is beautiful, and this lacks symmetry.

There seems to be an issue with #[repr(i128)] I discovered this when working on https://reviews.llvm.org/D149213
With the example program from the diff variables direct_tag_128_a and direct_tag_128_b give incorrect values in LLDB (with my change as you couldn't debug enums before).

Also something is wrong when those enums are defined as globals. Their values are completely off in both no_std and std compilations. I'm not 100% sure it's not LLDB issues or the change I did in LLDB but what I observed when debugging this is that this structure represents a variant

0x00000ab8:       DW_TAG_structure_type
                    DW_AT_name	("A")
                    DW_AT_byte_size	(0x18)
                    DW_AT_alignment	(8)

0x00000abf:         DW_TAG_member
                      DW_AT_name	("__0")
                      DW_AT_type	(0x00000b8f "u32")
                      DW_AT_alignment	(4)
                      DW_AT_data_member_location	(0x10)

__0 field having offset 16, but in reality in memory it was located at offset 8. So it's either the bug in debug info or in compiler.