-
Notifications
You must be signed in to change notification settings - Fork 22
Open
Labels
Description
When using the #[bitflags] macro, I encountered an issue where flags must have exactly one set bit. My code is as follows:
#[bitflags]
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum AiPrimitiveType {
Unknown = 0x00,
Point = 0x01,
Line = 0x02,
Triangle = 0x04,
Polygon = 0x08,
NgonEncodingFlag = 0x10,
}
This produces the following error:
error: Flags must have exactly one set bit
--> src/structs/mesh.rs:40:5
|
40 | Unknown = 0x00,
| ^^^^^^^
The error is caused by the check_flag logic:
if !n.is_power_of_two() {
Err(syn::Error::new(
flag.span,
"Flags must have exactly one set bit",
))
}
However, looking at the macro expansion:
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum AiPrimitiveType {
Point = 0x01,
Line = 0x02,
Triangle = 0x04,
Polygon = 0x08,
NgonEncodingFlag = 0x10,
}
impl ::enumflags2::_internal::core::ops::Not for AiPrimitiveType {
type Output = ::enumflags2::BitFlags<Self>;
#[inline(always)]
fn not(self) -> Self::Output {
use ::enumflags2::BitFlags;
BitFlags::from_flag(self).not()
}
}
impl ::enumflags2::_internal::core::ops::BitOr for AiPrimitiveType {
type Output = ::enumflags2::BitFlags<Self>;
#[inline(always)]
fn bitor(self, other: Self) -> Self::Output {
use ::enumflags2::BitFlags;
BitFlags::from_flag(self) | other
}
}
impl ::enumflags2::_internal::core::ops::BitAnd for AiPrimitiveType {
type Output = ::enumflags2::BitFlags<Self>;
#[inline(always)]
fn bitand(self, other: Self) -> Self::Output {
use ::enumflags2::BitFlags;
BitFlags::from_flag(self) & other
}
}
impl ::enumflags2::_internal::core::ops::BitXor for AiPrimitiveType {
type Output = ::enumflags2::BitFlags<Self>;
#[inline(always)]
fn bitxor(self, other: Self) -> Self::Output {
use ::enumflags2::BitFlags;
BitFlags::from_flag(self) ^ other
}
}
unsafe impl ::enumflags2::_internal::RawBitFlags for AiPrimitiveType {
type Numeric = u8;
const EMPTY: Self::Numeric = 0;
const DEFAULT: Self::Numeric = 0;
const ALL_BITS: Self::Numeric = 0
| (Self::Point as u8)
| (Self::Line as u8)
| (Self::Triangle as u8)
| (Self::Polygon as u8)
| (Self::NgonEncodingFlag as u8);
const BITFLAGS_TYPE_NAME: &'static str = "BitFlags<AiPrimitiveType>";
fn bits(self) -> Self::Numeric {
self as u8
}
}
impl ::enumflags2::BitFlag for AiPrimitiveType {}
This restriction seems unnecessary and limits usability, particularly for flags like Unknown = 0x00 or when defining named combinations. These combinations would naturally follow enum-to-u8 behavior as expected.
The only potential issue I see is with ALL_BITS as currently implemented. This could be resolved by ensuring it rounds up to the largest power of 2, setting all bits appropriately. Could this restriction be relaxed to allow more flexibility?