rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.58k stars 12.62k forks source link

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

Open Centril opened 5 years ago

Centril commented 5 years ago

This issue tracks repr128, i.e. "enums with 128-bit discriminant" as per https://github.com/rust-lang/rfcs/pull/1504. Originally this was tracked in https://github.com/rust-lang/rust/issues/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

clarfonthey commented 5 years ago

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?

nagisa commented 5 years ago

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.

marmeladema commented 3 years ago

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?

varkor commented 3 years ago

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

dan-da commented 3 years ago

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.

clarfonthey commented 3 years ago

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).

dan-da commented 3 years ago

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.

VladimirMakaev commented 1 year ago

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.

beetrees commented 2 months ago

__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.

@VladimirMakaev Is this still an issue? I've checked the example from the diff locally on Rust nightly and everything seems to agree that __0 it at offset 16 (straight after the 16-byte i128 discriminant).