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

Use Self & fix bug when overriding stringify! #249

Merged
merged 2 commits into from Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
116 changes: 52 additions & 64 deletions src/lib.rs
Expand Up @@ -362,6 +362,7 @@ macro_rules! bitflags {
() => {};
}

// A helper macro to implement the `all` function.
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __impl_all_bitflags {
Expand Down Expand Up @@ -389,12 +390,12 @@ macro_rules! __impl_all_bitflags {
}
)+
}
$BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag)|+ }
Self { bits: $(<Self as __BitFlags>::$Flag)|+ }
};
(
$BitFlags:ident: $T:ty { }
) => {
$BitFlags { bits: 0 }
Self { bits: 0 }
};
}

Expand Down Expand Up @@ -448,15 +449,15 @@ macro_rules! __impl_bitflags {

let mut first = true;
$(
if <$BitFlags as __BitFlags>::$Flag(self) {
if <Self as __BitFlags>::$Flag(self) {
if !first {
f.write_str(" | ")?;
}
first = false;
f.write_str(__bitflags_stringify!($Flag))?;
f.write_str($crate::_core::stringify!($Flag))?;
}
)*
let extra_bits = self.bits & !$BitFlags::all().bits();
let extra_bits = self.bits & !Self::all().bits();
if extra_bits != 0 {
if !first {
f.write_str(" | ")?;
Expand Down Expand Up @@ -496,18 +497,18 @@ macro_rules! __impl_bitflags {
impl $BitFlags {
$(
$(#[$attr $($args)*])*
pub const $Flag: $BitFlags = $BitFlags { bits: $value };
pub const $Flag: Self = Self { bits: $value };
)*

/// Returns an empty set of flags.
#[inline]
pub const fn empty() -> $BitFlags {
$BitFlags { bits: 0 }
pub const fn empty() -> Self {
Self { bits: 0 }
}

/// Returns the set containing all flags.
#[inline]
pub const fn all() -> $BitFlags {
pub const fn all() -> Self {
__impl_all_bitflags! {
$BitFlags: $T {
$(
Expand All @@ -527,9 +528,9 @@ macro_rules! __impl_bitflags {
/// Convert from underlying bit representation, unless that
/// representation contains bits that do not correspond to a flag.
#[inline]
pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
if (bits & !$BitFlags::all().bits()) == 0 {
$crate::_core::option::Option::Some($BitFlags { bits })
pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> {
if (bits & !Self::all().bits()) == 0 {
$crate::_core::option::Option::Some(Self { bits })
} else {
$crate::_core::option::Option::None
}
Expand All @@ -538,8 +539,8 @@ macro_rules! __impl_bitflags {
/// Convert from underlying bit representation, dropping any bits
/// that do not correspond to flags.
#[inline]
pub const fn from_bits_truncate(bits: $T) -> $BitFlags {
$BitFlags { bits: bits & $BitFlags::all().bits }
pub const fn from_bits_truncate(bits: $T) -> Self {
Self { bits: bits & Self::all().bits }
}

/// Convert from underlying bit representation, preserving all
Expand All @@ -554,54 +555,55 @@ macro_rules! __impl_bitflags {
/// all bits correspond to a defined flag or that extra bits
/// are valid for this bitflags type.
#[inline]
pub const unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
$BitFlags { bits }
pub const unsafe fn from_bits_unchecked(bits: $T) -> Self {
Self { bits }
}

/// Returns `true` if no flags are currently stored.
#[inline]
pub const fn is_empty(&self) -> bool {
self.bits() == $BitFlags::empty().bits()
self.bits() == Self::empty().bits()
}

/// Returns `true` if all flags are currently set.
#[inline]
pub const fn is_all(&self) -> bool {
$BitFlags::all().bits | self.bits == self.bits
Self::all().bits | self.bits == self.bits
}

/// Returns `true` if there are flags common to both `self` and `other`.
#[inline]
pub const fn intersects(&self, other: $BitFlags) -> bool {
!$BitFlags{ bits: self.bits & other.bits}.is_empty()
pub const fn intersects(&self, other: Self) -> bool {
!(Self { bits: self.bits & other.bits}).is_empty()
}

/// Returns `true` if all of the flags in `other` are contained within `self`.
#[inline]
pub const fn contains(&self, other: $BitFlags) -> bool {
pub const fn contains(&self, other: Self) -> bool {
(self.bits & other.bits) == other.bits
}

/// Inserts the specified flags in-place.
#[inline]
pub fn insert(&mut self, other: $BitFlags) {
pub fn insert(&mut self, other: Self) {
self.bits |= other.bits;
}

/// Removes the specified flags in-place.
#[inline]
pub fn remove(&mut self, other: $BitFlags) {
pub fn remove(&mut self, other: Self) {
self.bits &= !other.bits;
}

/// Toggles the specified flags in-place.
#[inline]
pub fn toggle(&mut self, other: $BitFlags) {
pub fn toggle(&mut self, other: Self) {
self.bits ^= other.bits;
}

/// Inserts or removes the specified flags depending on the passed value.
#[inline]
pub fn set(&mut self, other: $BitFlags, value: bool) {
pub fn set(&mut self, other: Self, value: bool) {
if value {
self.insert(other);
} else {
Expand All @@ -621,7 +623,7 @@ macro_rules! __impl_bitflags {
/// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
#[inline]
#[must_use]
pub const fn intersection(self, other: $BitFlags) -> Self {
pub const fn intersection(self, other: Self) -> Self {
Self { bits: self.bits & other.bits }
}

Expand All @@ -638,7 +640,7 @@ macro_rules! __impl_bitflags {
/// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
#[inline]
#[must_use]
pub const fn union(self, other: $BitFlags) -> Self {
pub const fn union(self, other: Self) -> Self {
Self { bits: self.bits | other.bits }
}

Expand All @@ -656,7 +658,7 @@ macro_rules! __impl_bitflags {
/// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
#[inline]
#[must_use]
pub const fn difference(self, other: $BitFlags) -> Self {
pub const fn difference(self, other: Self) -> Self {
Self { bits: self.bits & !other.bits }
}

Expand All @@ -675,7 +677,7 @@ macro_rules! __impl_bitflags {
/// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: $BitFlags) -> Self {
pub const fn symmetric_difference(self, other: Self) -> Self {
Self { bits: self.bits ^ other.bits }
}

Expand All @@ -701,101 +703,97 @@ macro_rules! __impl_bitflags {
}

impl $crate::_core::ops::BitOr for $BitFlags {
type Output = $BitFlags;
type Output = Self;

/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits | other.bits }
fn bitor(self, other: $BitFlags) -> Self {
Self { bits: self.bits | other.bits }
}
}

impl $crate::_core::ops::BitOrAssign for $BitFlags {

/// Adds the set of flags.
#[inline]
fn bitor_assign(&mut self, other: $BitFlags) {
fn bitor_assign(&mut self, other: Self) {
self.bits |= other.bits;
}
}

impl $crate::_core::ops::BitXor for $BitFlags {
type Output = $BitFlags;
type Output = Self;

/// Returns the left flags, but with all the right flags toggled.
#[inline]
fn bitxor(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits ^ other.bits }
fn bitxor(self, other: Self) -> Self {
Self { bits: self.bits ^ other.bits }
}
}

impl $crate::_core::ops::BitXorAssign for $BitFlags {

/// Toggles the set of flags.
#[inline]
fn bitxor_assign(&mut self, other: $BitFlags) {
fn bitxor_assign(&mut self, other: Self) {
self.bits ^= other.bits;
}
}

impl $crate::_core::ops::BitAnd for $BitFlags {
type Output = $BitFlags;
type Output = Self;

/// Returns the intersection between the two sets of flags.
#[inline]
fn bitand(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & other.bits }
fn bitand(self, other: Self) -> Self {
Self { bits: self.bits & other.bits }
}
}

impl $crate::_core::ops::BitAndAssign for $BitFlags {

/// Disables all flags disabled in the set.
#[inline]
fn bitand_assign(&mut self, other: $BitFlags) {
fn bitand_assign(&mut self, other: Self) {
self.bits &= other.bits;
}
}

impl $crate::_core::ops::Sub for $BitFlags {
type Output = $BitFlags;
type Output = Self;

/// Returns the set difference of the two sets of flags.
#[inline]
fn sub(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & !other.bits }
fn sub(self, other: Self) -> Self {
Self { bits: self.bits & !other.bits }
}
}

impl $crate::_core::ops::SubAssign for $BitFlags {

/// Disables all flags enabled in the set.
#[inline]
fn sub_assign(&mut self, other: $BitFlags) {
fn sub_assign(&mut self, other: Self) {
self.bits &= !other.bits;
}
}

impl $crate::_core::ops::Not for $BitFlags {
type Output = $BitFlags;
type Output = Self;

/// Returns the complement of this set of flags.
#[inline]
fn not(self) -> $BitFlags {
$BitFlags { bits: !self.bits } & $BitFlags::all()
fn not(self) -> Self {
Self { bits: !self.bits } & Self::all()
}
}

impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) {
fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) {
for item in iterator {
self.insert(item)
}
}
}

impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self {
let mut result = Self::empty();
result.extend(iterator);
result
Expand Down Expand Up @@ -912,16 +910,6 @@ macro_rules! __impl_bitflags {
};
}

// Same as std::stringify but callable from __impl_bitflags, which needs to use
// local_inner_macros so can only directly call macros from this crate.
#[macro_export]
#[doc(hidden)]
macro_rules! __bitflags_stringify {
($s:ident) => {
stringify!($s)
};
}

#[cfg(feature = "example_generated")]
pub mod example_generated;

Expand Down
9 changes: 0 additions & 9 deletions tests/redefine_core.rs

This file was deleted.

22 changes: 22 additions & 0 deletions tests/redefinition.rs
@@ -0,0 +1,22 @@
use bitflags::bitflags;

// Checks for possible errors caused by overriding names used by `bitflags!` internally.

mod core {}
mod _core {}

#[allow(unused_macros)]
macro_rules! stringify {
($($t:tt)*) => { "..." };
}

bitflags! {
struct Test: u8 {
const A = 1;
}
}

#[test]
fn stringify() {
assert_eq!(format!("{:?}", Test::A), "A");
}