Split bitflags macro and traits into 2.5 macros/traits #419

Open
opened 2024-08-13 13:29:47 -05:00 by rusty-snake · 2 comments
rusty-snake commented 2024-08-13 13:29:47 -05:00 (Migrated from github.com)

This issue tries to outline a solution to some of the problems of bitflags. There is plenty room for discussion right now.

bitflag suffers from the fact that it hadn't a defined target group for a long time and got request from different directions with different requirements. This improved over the last releases and we now have largely consistent behaviour and a definition of the status quo. However this is still a compromise that does neither bring the one side full feature power nor the other.

The overall idea is to have more than one bitflags type (type here means macro/trait = API).

FFIFlagsWeak / FFIFlagsStrict

One major use of bitflags is for type-safe ffi types commonly found on C APIs.

  • The most important aspect here is that we deal with foreign flags where the integer-type and the flag values have to be an explicit defined value. Comparable with #[repr(C)].
  • For some APIs passing new (undefined) flags is a tolerated/required feature. While other APIs need to consider every other bit as dangerous. Hence the needs to be a weak and a strict variant.
  • Strange flags (e.g. multi-bit, ...) might be part of the API and we can not forbid them. We do not necessarily need full support for such flags in the first place (e.g. from/to string) but we need to handle them gracefully w/o assuming magic.

RustFlags

The second use are sane, type-safe, well-defined, comfortable Rust-to-Rust APIs.

  • The exact flag values and integer-type does not matter as long as they are stable for one compilation. Comparable with #[repr(Rust)].
    • This allows stuff like auto flags.
  • We can be strict on strange flags.
  • There is no need to expose the raw bits.
  • We really only want a optimized and convenient struct { bool, bool, bool, bool, bool, bool, bool, bool }
This issue tries to outline a solution to some of the problems of bitflags. There is plenty room for discussion right now. bitflag suffers from the fact that it hadn't a defined target group for a long time and got request from different directions with different requirements. This improved over the last releases and we now have largely consistent behaviour and a definition of the status quo. However this is still a compromise that does neither bring the one side full feature power nor the other. The overall idea is to have more than one bitflags type (type here means macro/trait = API). ### `FFIFlagsWeak` / `FFIFlagsStrict` One major use of `bitflags` is for type-safe ffi types commonly found on C APIs. - The most important aspect here is that we deal with foreign flags where the integer-type and the flag values have to be an explicit defined value. Comparable with `#[repr(C)]`. - For some APIs passing new (undefined) flags is a tolerated/required feature. While other APIs need to consider every other bit as dangerous. Hence the needs to be a weak and a strict variant. - Strange flags (e.g. multi-bit, ...) might be part of the API and we can not forbid them. We do not necessarily need full support for such flags in the first place (e.g. from/to string) but we need to handle them gracefully w/o assuming magic. ### `RustFlags` The second use are sane, type-safe, well-defined, comfortable Rust-to-Rust APIs. - The exact flag values and integer-type does not matter as long as they are stable for one compilation. Comparable with `#[repr(Rust)]`. - This allows stuff like `auto` flags. - We can be strict on strange flags. - There is no need to expose the raw bits. - We really only want a optimized and convenient `struct { bool, bool, bool, bool, bool, bool, bool, bool }`
KodrAus commented 2024-09-14 04:43:27 -05:00 (Migrated from github.com)

The tension between these has definitely caused us trouble in the past, and we've largely started catering to the former group more than the latter these days. For the latter group, I've thought a proc-macro library that was fully strict might be a good fit. There are a few out there already, such as this one, but I'm not sure how far they go to deal with the oddities around multi-bit flags, which I think should be disallowed, like your example of basically producing a struct of bools.

The tension between these has definitely caused us trouble in the past, and we've largely started catering to the former group more than the latter these days. For the latter group, I've thought a proc-macro library that was fully strict might be a good fit. There are a few out there already, such as [this one](https://github.com/meithecatte/enumflags2), but I'm not sure how far they go to deal with the oddities around multi-bit flags, which I think should be disallowed, like your example of basically producing a struct of bools.
KodrAus commented 2024-09-14 04:45:57 -05:00 (Migrated from github.com)

I think there's definitely room for a library that took the approach of if flags types were going to be a language feature in Rust, how would they work? and would love to see it get built.

I think there's definitely room for a library that took the approach of _if flags types were going to be a language feature in Rust, how would they work?_ and would love to see it get built.
Sign in to join this conversation.
No labels
bug
good first issue
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-bitflags/bitflags#419
No description provided.