Update to 2.3.2. am: ff6563b406

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/bitflags/+/2624429

Change-Id: I2ec58a0ce04858d45a78e50eca33f2057d09ad95
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index b28c102..6877a2f 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "0c318c0d77ed63ad4ee9bfdf1d2c486993b18b37"
+    "sha1": "09f71f492d0f76d63cd286c3869c70676297e204"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
deleted file mode 100644
index ffe0eda..0000000
--- a/.github/workflows/rust.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-name: Rust
-
-on: [push, pull_request]
-
-env:
-  CARGO_TERM_COLOR: always
-
-jobs:
-  check:
-    name: Test
-    runs-on: ubuntu-latest
-    strategy:
-      fail-fast: true
-      matrix:
-        rust:
-          - stable
-          - beta
-          - nightly
-          - 1.46.0
-    steps:
-      - name: Checkout sources
-        uses: actions/checkout@v2
-
-      - name: Install Rust toolchain
-        uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: ${{ matrix.rust }}
-          override: true
-
-      - name: Default features
-        uses: actions-rs/cargo@v1
-        with:
-          command: test
-          args: --features example_generated
-
-  embedded:
-    name: Build (embedded)
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout sources
-        uses: actions/checkout@v2
-
-      - name: Install Rust toolchain
-        uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: nightly
-          target: thumbv6m-none-eabi
-          override: true
-
-      - name: Default features
-        uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: -Z avoid-dev-deps --features example_generated --target thumbv6m-none-eabi
diff --git a/Android.bp b/Android.bp
index a6761c1..6d4d347 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@
     host_supported: true,
     crate_name: "bitflags",
     cargo_env_compat: true,
-    cargo_pkg_version: "2.2.1",
+    cargo_pkg_version: "2.3.2",
     srcs: ["src/lib.rs"],
     edition: "2021",
     apex_available: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c6df58..5512ceb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+# 2.3.2
+
+## What's Changed
+* [doc] [src/lib.rs]  delete redundant path prefix by @OccupyMars2025 in https://github.com/bitflags/bitflags/pull/361
+
+## New Contributors
+* @OccupyMars2025 made their first contribution in https://github.com/bitflags/bitflags/pull/361
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.3.1...2.3.2
+
+# 2.3.1
+
+## What's Changed
+* Fix Self in flags value expressions by @KodrAus in https://github.com/bitflags/bitflags/pull/355
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.3.0...2.3.1
+
+# 2.3.0
+
+## What's Changed
+* Support ejecting flags types from the bitflags macro by @KodrAus in https://github.com/bitflags/bitflags/pull/351
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.2.1...2.3.0
+
 # 2.2.1
 
 ## What's Changed
diff --git a/Cargo.toml b/Cargo.toml
index 06afeef..7b9cfb0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2021"
 rust-version = "1.56.0"
 name = "bitflags"
-version = "2.2.1"
+version = "2.3.2"
 authors = ["The Rust Project Developers"]
 exclude = [
     "tests",
@@ -83,6 +83,9 @@
 [dev-dependencies.trybuild]
 version = "1.0"
 
+[dev-dependencies.zerocopy]
+version = "0.6"
+
 [features]
 example_generated = []
 rustc-dep-of-std = [
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index a239132..7d57882 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -3,7 +3,7 @@
 # NB: When modifying, also modify:
 #   1. html_root_url in lib.rs
 #   2. number in readme (for breaking changes)
-version = "2.2.1"
+version = "2.3.2"
 edition = "2021"
 rust-version = "1.56.0"
 authors = ["The Rust Project Developers"]
@@ -32,6 +32,7 @@
 serde_derive = "1.0"
 serde_json = "1.0"
 serde_test = "1.0"
+zerocopy = "0.6"
 arbitrary = { version = "1.0", features = ["derive"] }
 bytemuck = { version = "1.0", features = ["derive"] }
 
diff --git a/METADATA b/METADATA
index a0bd701..0872db8 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/bitflags/bitflags-2.2.1.crate"
+    value: "https://static.crates.io/crates/bitflags/bitflags-2.3.2.crate"
   }
-  version: "2.2.1"
+  version: "2.3.2"
   license_type: NOTICE
   last_upgrade_date {
     year: 2023
-    month: 4
-    day: 26
+    month: 6
+    day: 13
   }
 }
diff --git a/README.md b/README.md
index f9a5bb4..fada7a6 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
 
 ```toml
 [dependencies]
-bitflags = "2.2.1"
+bitflags = "2.3.2"
 ```
 
 and this to your source code:
diff --git a/examples/custom_bits_type.rs b/examples/custom_bits_type.rs
new file mode 100644
index 0000000..0364a2b
--- /dev/null
+++ b/examples/custom_bits_type.rs
@@ -0,0 +1,85 @@
+use std::ops::{BitAnd, BitOr, BitXor, Not};
+
+use bitflags::{Flags, Flag, Bits};
+
+// Define a custom container that can be used in flags types
+// Note custom bits types can't be used in `bitflags!`
+// without making the trait impls `const`. This is currently
+// unstable
+#[derive(Clone, Copy, Debug)]
+pub struct CustomBits([bool; 3]);
+
+impl Bits for CustomBits {
+    const EMPTY: Self = CustomBits([false; 3]);
+
+    const ALL: Self = CustomBits([true; 3]);
+}
+
+impl PartialEq for CustomBits {
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl BitAnd for CustomBits {
+    type Output = Self;
+
+    fn bitand(self, other: Self) -> Self {
+        CustomBits([self.0[0] & other.0[0], self.0[1] & other.0[1], self.0[2] & other.0[2]])
+    }
+}
+
+impl BitOr for CustomBits {
+    type Output = Self;
+
+    fn bitor(self, other: Self) -> Self {
+        CustomBits([self.0[0] | other.0[0], self.0[1] | other.0[1], self.0[2] | other.0[2]])
+    }
+}
+
+impl BitXor for CustomBits {
+    type Output = Self;
+
+    fn bitxor(self, other: Self) -> Self {
+        CustomBits([self.0[0] & other.0[0], self.0[1] & other.0[1], self.0[2] & other.0[2]])
+    }
+}
+
+impl Not for CustomBits {
+    type Output = Self;
+
+    fn not(self) -> Self {
+        CustomBits([!self.0[0], !self.0[1], !self.0[2]])
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct CustomFlags(CustomBits);
+
+impl CustomFlags {
+    pub const A: Self = CustomFlags(CustomBits([true, false, false]));
+    pub const B: Self = CustomFlags(CustomBits([false, true, false]));
+    pub const C: Self = CustomFlags(CustomBits([false, false, true]));
+}
+
+impl Flags for CustomFlags {
+    const FLAGS: &'static [Flag<Self>] = &[
+        Flag::new("A", Self::A),
+        Flag::new("B", Self::B),
+        Flag::new("C", Self::C),
+    ];
+
+    type Bits = CustomBits;
+
+    fn bits(&self) -> Self::Bits {
+        self.0
+    }
+
+    fn from_bits_retain(bits: Self::Bits) -> Self {
+        CustomFlags(bits)
+    }
+}
+
+fn main() {
+    println!("{:?}", CustomFlags::A.union(CustomFlags::C));
+}
diff --git a/examples/custom_derive.rs b/examples/custom_derive.rs
new file mode 100644
index 0000000..5a85afb
--- /dev/null
+++ b/examples/custom_derive.rs
@@ -0,0 +1,23 @@
+//! An example of implementing the `BitFlags` trait manually for a flags type.
+
+use std::str;
+
+use bitflags::bitflags;
+
+// Define a flags type outside of the `bitflags` macro as a newtype
+// It can accept custom derives for libaries `bitflags` doesn't support natively
+#[derive(zerocopy::AsBytes, zerocopy::FromBytes)]
+#[repr(transparent)]
+pub struct ManualFlags(u32);
+
+// Next: use `impl Flags` instead of `struct Flags`
+bitflags! {
+    impl ManualFlags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+    }
+}
+
+fn main() {}
diff --git a/examples/fmt.rs b/examples/fmt.rs
index 3bb9b8c..724b207 100644
--- a/examples/fmt.rs
+++ b/examples/fmt.rs
@@ -2,40 +2,40 @@
 
 use core::{fmt, str};
 
+bitflags::bitflags! {
+    // You can `#[derive]` the `Debug` trait, but implementing it manually
+    // can produce output like `A | B` instead of `Flags(A | B)`.
+    // #[derive(Debug)]
+    #[derive(PartialEq, Eq)]
+    pub struct Flags: u32 {
+        const A = 1;
+        const B = 2;
+        const C = 4;
+        const D = 8;
+    }
+}
+
+impl fmt::Debug for Flags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        bitflags::parser::to_writer(self, f)
+    }
+}
+
+impl fmt::Display for Flags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        bitflags::parser::to_writer(self, f)
+    }
+}
+
+impl str::FromStr for Flags {
+    type Err = bitflags::parser::ParseError;
+
+    fn from_str(flags: &str) -> Result<Self, Self::Err> {
+        bitflags::parser::from_str(flags)
+    }
+}
+
 fn main() -> Result<(), bitflags::parser::ParseError> {
-    bitflags::bitflags! {
-        // You can `#[derive]` the `Debug` trait, but implementing it manually
-        // can produce output like `A | B` instead of `Flags(A | B)`.
-        // #[derive(Debug)]
-        #[derive(PartialEq, Eq)]
-        pub struct Flags: u32 {
-            const A = 1;
-            const B = 2;
-            const C = 4;
-            const D = 8;
-        }
-    }
-
-    impl fmt::Debug for Flags {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            fmt::Debug::fmt(&self.0, f)
-        }
-    }
-
-    impl fmt::Display for Flags {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            fmt::Display::fmt(&self.0, f)
-        }
-    }
-
-    impl str::FromStr for Flags {
-        type Err = bitflags::parser::ParseError;
-
-        fn from_str(flags: &str) -> Result<Self, Self::Err> {
-            Ok(Self(flags.parse()?))
-        }
-    }
-
     let flags = Flags::A | Flags::B;
 
     println!("{}", flags);
diff --git a/examples/macro_free.rs b/examples/macro_free.rs
new file mode 100644
index 0000000..ec3a8cb
--- /dev/null
+++ b/examples/macro_free.rs
@@ -0,0 +1,58 @@
+//! An example of implementing the `BitFlags` trait manually for a flags type.
+//!
+//! This example doesn't use any macros.
+
+use std::{fmt, str};
+
+use bitflags::{Flags, Flag};
+
+// First: Define your flags type. It just needs to be `Sized + 'static`.
+pub struct ManualFlags(u32);
+
+// Not required: Define some constants for valid flags
+impl ManualFlags {
+    pub const A: ManualFlags = ManualFlags(0b00000001);
+    pub const B: ManualFlags = ManualFlags(0b00000010);
+    pub const C: ManualFlags = ManualFlags(0b00000100);
+    pub const ABC: ManualFlags = ManualFlags(0b00000111);
+}
+
+// Next: Implement the `BitFlags` trait, specifying your set of valid flags
+// and iterators
+impl Flags for ManualFlags {
+    const FLAGS: &'static [Flag<Self>] = &[
+        Flag::new("A", Self::A),
+        Flag::new("B", Self::B),
+        Flag::new("C", Self::C),
+    ];
+
+    type Bits = u32;
+
+    fn bits(&self) -> u32 {
+        self.0
+    }
+
+    fn from_bits_retain(bits: u32) -> Self {
+        Self(bits)
+    }
+}
+
+// Not required: Add parsing support
+impl str::FromStr for ManualFlags {
+    type Err = bitflags::parser::ParseError;
+
+    fn from_str(input: &str) -> Result<Self, Self::Err> {
+        bitflags::parser::from_str(input)
+    }
+}
+
+// Not required: Add formatting support
+impl fmt::Display for ManualFlags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        bitflags::parser::to_writer(self, f)
+    }
+}
+
+fn main() {
+    println!("{}", ManualFlags::A.union(ManualFlags::B).union(ManualFlags::C));
+}
diff --git a/src/example_generated.rs b/src/example_generated.rs
index b758901..7f8a5c5 100644
--- a/src/example_generated.rs
+++ b/src/example_generated.rs
@@ -9,30 +9,41 @@
     /// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
     /// Note that this struct is just for documentation purposes only, it must not be used outside
     /// this crate.
-    pub struct Flags;
+    pub struct Flags
 }
 
 __declare_internal_bitflags! {
-    pub struct Field0: u32;
-    pub struct Iter;
-    pub struct IterRaw;
+    pub struct Field0: u32
 }
 
 __impl_internal_bitflags! {
-    Field0: u32, Flags, Iter, IterRaw {
-        A;
-        B;
-        C;
-        ABC;
+    Field0: u32, Flags {
+        // Field `A`.
+        ///
+        /// This flag has the value `0b00000001`.
+        A = 0b00000001;
+        /// Field `B`.
+        ///
+        /// This flag has the value `0b00000010`.
+        B = 0b00000010;
+        /// Field `C`.
+        ///
+        /// This flag has the value `0b00000100`.
+        C = 0b00000100;
+        ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
     }
 }
 
-__impl_public_bitflags! {
-    Flags: u32, Field0, Iter, IterRaw;
+__impl_public_bitflags_forward! {
+    Flags: u32, Field0
+}
+
+__impl_public_bitflags_iter! {
+    Flags: u32, Flags
 }
 
 __impl_public_bitflags_consts! {
-    Flags {
+    Flags: u32 {
         /// Field `A`.
         ///
         /// This flag has the value `0b00000001`.
diff --git a/src/external.rs b/src/external.rs
index 6b07ff6..103b5d1 100644
--- a/src/external.rs
+++ b/src/external.rs
@@ -5,7 +5,13 @@
 
 Let's say we want to add support for `my_library`.
 
-First, we define a macro like so:
+First, we create a module under `external`, like `serde` with any specialized code.
+Ideally, any utilities in here should just work off the `Flags` trait and maybe a
+few other assumed bounds.
+
+Next, re-export the library from the `__private` module here.
+
+Next, define a macro like so:
 
 ```rust
 #[macro_export(local_inner_macros)]
@@ -13,7 +19,7 @@
 #[cfg(feature = "serde")]
 macro_rules! __impl_external_bitflags_my_library {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident;
@@ -29,7 +35,7 @@
 #[cfg(not(feature = "my_library"))]
 macro_rules! __impl_external_bitflags_my_library {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident;
@@ -49,7 +55,7 @@
 
 ```rust
 __impl_external_bitflags_my_library! {
-    $InternalBitFlags: $T {
+    $InternalBitFlags: $T, $PublicBitFlags {
         $(
             $(#[$attr $($args)*])*
             $Flag;
@@ -57,34 +63,25 @@
     }
 }
 ```
-
-What about libraries that _must_ be supported through `#[derive]`?
-
-In these cases, the attributes will need to be added to the `__declare_internal_bitflags` macro when
-the internal type is declared.
 */
 
-#[cfg(feature = "serde")]
-pub mod serde_support;
-#[cfg(feature = "serde")]
-pub use serde;
+pub(crate) mod __private {
+    #[cfg(feature = "serde")]
+    pub use serde;
 
-#[cfg(feature = "arbitrary")]
-pub mod arbitrary_support;
-#[cfg(feature = "arbitrary")]
-pub use arbitrary;
+    #[cfg(feature = "arbitrary")]
+    pub use arbitrary;
 
-#[cfg(feature = "bytemuck")]
-pub mod bytemuck_support;
-#[cfg(feature = "bytemuck")]
-pub use bytemuck;
+    #[cfg(feature = "bytemuck")]
+    pub use bytemuck;
+}
 
 /// Implements traits from external libraries for the internal bitflags type.
 #[macro_export(local_inner_macros)]
 #[doc(hidden)]
 macro_rules! __impl_external_bitflags {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident;
@@ -96,7 +93,7 @@
         // and a no-op when it isn't
 
         __impl_external_bitflags_serde! {
-            $InternalBitFlags: $T {
+            $InternalBitFlags: $T, $PublicBitFlags {
                 $(
                     $(#[$attr $($args)*])*
                     $Flag;
@@ -105,7 +102,7 @@
         }
 
         __impl_external_bitflags_arbitrary! {
-            $InternalBitFlags: $T {
+            $InternalBitFlags: $T, $PublicBitFlags {
                 $(
                     $(#[$attr $($args)*])*
                     $Flag;
@@ -114,7 +111,7 @@
         }
 
         __impl_external_bitflags_bytemuck! {
-            $InternalBitFlags: $T {
+            $InternalBitFlags: $T, $PublicBitFlags {
                 $(
                     $(#[$attr $($args)*])*
                     $Flag;
@@ -124,13 +121,16 @@
     };
 }
 
+#[cfg(feature = "serde")]
+pub mod serde;
+
 /// Implement `Serialize` and `Deserialize` for the internal bitflags type.
 #[macro_export(local_inner_macros)]
 #[doc(hidden)]
 #[cfg(feature = "serde")]
 macro_rules! __impl_external_bitflags_serde {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident;
@@ -142,8 +142,8 @@
                 &self,
                 serializer: S,
             ) -> $crate::__private::core::result::Result<S::Ok, S::Error> {
-                $crate::__private::serde_support::serialize_bits_default::<$InternalBitFlags, $T, S>(
-                    &self,
+                $crate::serde::serialize(
+                    &$PublicBitFlags::from_bits_retain(self.bits()),
                     serializer,
                 )
             }
@@ -153,9 +153,11 @@
             fn deserialize<D: $crate::__private::serde::Deserializer<'de>>(
                 deserializer: D,
             ) -> $crate::__private::core::result::Result<Self, D::Error> {
-                $crate::__private::serde_support::deserialize_bits_default::<$InternalBitFlags, $T, D>(
+                let flags: $PublicBitFlags = $crate::serde::deserialize(
                     deserializer,
-                )
+                )?;
+
+                Ok(flags.0)
             }
         }
     };
@@ -166,7 +168,7 @@
 #[cfg(not(feature = "serde"))]
 macro_rules! __impl_external_bitflags_serde {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident;
@@ -175,13 +177,19 @@
     ) => {};
 }
 
+#[cfg(feature = "arbitrary")]
+pub mod arbitrary;
+
+#[cfg(feature = "bytemuck")]
+mod bytemuck;
+
 /// Implement `Arbitrary` for the internal bitflags type.
 #[macro_export(local_inner_macros)]
 #[doc(hidden)]
 #[cfg(feature = "arbitrary")]
 macro_rules! __impl_external_bitflags_arbitrary {
     (
-            $InternalBitFlags:ident: $T:ty {
+            $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
                 $(
                     $(#[$attr:ident $($args:tt)*])*
                     $Flag:ident;
@@ -192,7 +200,7 @@
             fn arbitrary(
                 u: &mut $crate::__private::arbitrary::Unstructured<'a>,
             ) -> $crate::__private::arbitrary::Result<Self> {
-                Self::from_bits(u.arbitrary()?).ok_or_else(|| $crate::__private::arbitrary::Error::IncorrectFormat)
+                $crate::arbitrary::arbitrary::<$PublicBitFlags>(u).map(|flags| flags.0)
             }
         }
     };
@@ -203,12 +211,12 @@
 #[cfg(not(feature = "arbitrary"))]
 macro_rules! __impl_external_bitflags_arbitrary {
     (
-            $InternalBitFlags:ident: $T:ty {
-                $(
-                    $(#[$attr:ident $($args:tt)*])*
-                    $Flag:ident;
-                )*
-            }
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
+            $(
+                $(#[$attr:ident $($args:tt)*])*
+                $Flag:ident;
+            )*
+        }
     ) => {};
 }
 
@@ -218,11 +226,11 @@
 #[cfg(feature = "bytemuck")]
 macro_rules! __impl_external_bitflags_bytemuck {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
-                    $Flag:ident;
-                )*
+                $Flag:ident;
+            )*
         }
     ) => {
         // SAFETY: $InternalBitFlags is guaranteed to have the same ABI as $T,
@@ -250,11 +258,11 @@
 #[cfg(not(feature = "bytemuck"))]
 macro_rules! __impl_external_bitflags_bytemuck {
     (
-        $InternalBitFlags:ident: $T:ty {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
-                    $Flag:ident;
-                )*
+                $Flag:ident;
+            )*
         }
     ) => {};
 }
diff --git a/src/external/arbitrary.rs b/src/external/arbitrary.rs
new file mode 100644
index 0000000..ae59677
--- /dev/null
+++ b/src/external/arbitrary.rs
@@ -0,0 +1,33 @@
+//! Specialized fuzzing for flags types using `arbitrary`.
+
+use crate::Flags;
+
+/// Get a random known flags value.
+pub fn arbitrary<'a, B: Flags>(
+    u: &mut arbitrary::Unstructured<'a>,
+) -> arbitrary::Result<B>
+where
+    B::Bits: arbitrary::Arbitrary<'a>
+{
+    B::from_bits(u.arbitrary()?).ok_or_else(|| arbitrary::Error::IncorrectFormat)
+}
+
+#[cfg(test)]
+mod tests {
+    use arbitrary::Arbitrary;
+
+    bitflags! {
+        #[derive(Arbitrary)]
+        struct Color: u32 {
+            const RED = 0x1;
+            const GREEN = 0x2;
+            const BLUE = 0x4;
+        }
+    }
+
+    #[test]
+    fn test_arbitrary() {
+        let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]);
+        let _color = Color::arbitrary(&mut unstructured);
+    }
+}
diff --git a/src/external/arbitrary_support.rs b/src/external/arbitrary_support.rs
deleted file mode 100644
index 56708f0..0000000
--- a/src/external/arbitrary_support.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#[cfg(test)]
-mod tests {
-    use arbitrary::Arbitrary;
-
-    bitflags! {
-        #[derive(Arbitrary)]
-        struct Color: u32 {
-            const RED = 0x1;
-            const GREEN = 0x2;
-            const BLUE = 0x4;
-        }
-    }
-
-    #[test]
-    fn test_arbitrary() {
-        let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]);
-        let _color = Color::arbitrary(&mut unstructured);
-    }
-}
diff --git a/src/external/bytemuck_support.rs b/src/external/bytemuck.rs
similarity index 100%
rename from src/external/bytemuck_support.rs
rename to src/external/bytemuck.rs
diff --git a/src/external/serde_support.rs b/src/external/serde.rs
similarity index 64%
rename from src/external/serde_support.rs
rename to src/external/serde.rs
index 7c202a2..bc1f2ec 100644
--- a/src/external/serde_support.rs
+++ b/src/external/serde.rs
@@ -1,59 +1,66 @@
+//! Specialized serialization for flags types using `serde`.
+
 use core::{fmt, str};
+use crate::{Flags, parser::{self, ParseHex, WriteHex}};
 use serde::{
     de::{Error, Visitor},
     Deserialize, Deserializer, Serialize, Serializer,
 };
 
-pub fn serialize_bits_default<T: fmt::Display + AsRef<B>, B: Serialize, S: Serializer>(
-    flags: &T,
+/// Serialize a set of flags as a human-readable string or their underlying bits.
+pub fn serialize<B: Flags, S: Serializer>(
+    flags: &B,
     serializer: S,
-) -> Result<S::Ok, S::Error> {
+) -> Result<S::Ok, S::Error>
+where
+    B::Bits: WriteHex + Serialize,
+{
     // Serialize human-readable flags as a string like `"A | B"`
     if serializer.is_human_readable() {
-        serializer.collect_str(flags)
+        serializer.collect_str(&parser::AsDisplay(flags))
     }
     // Serialize non-human-readable flags directly as the underlying bits
     else {
-        flags.as_ref().serialize(serializer)
+        flags.bits().serialize(serializer)
     }
 }
 
-pub fn deserialize_bits_default<
+/// Deserialize a set of flags from a human-readable string or their underlying bits.
+pub fn deserialize<
     'de,
-    T: str::FromStr + From<B>,
-    B: Deserialize<'de>,
+    B: Flags,
     D: Deserializer<'de>,
 >(
     deserializer: D,
-) -> Result<T, D::Error>
+) -> Result<B, D::Error>
 where
-    <T as str::FromStr>::Err: fmt::Display,
+    B::Bits: ParseHex + Deserialize<'de>,
 {
     if deserializer.is_human_readable() {
         // Deserialize human-readable flags by parsing them from strings like `"A | B"`
-        struct FlagsVisitor<T>(core::marker::PhantomData<T>);
+        struct FlagsVisitor<B>(core::marker::PhantomData<B>);
 
-        impl<'de, T: str::FromStr> Visitor<'de> for FlagsVisitor<T>
+        impl<'de, B: Flags> Visitor<'de> for FlagsVisitor<B>
         where
-            <T as str::FromStr>::Err: fmt::Display,
+            B::Bits: ParseHex,
         {
-            type Value = T;
+            type Value = B;
 
             fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                 formatter.write_str("a string value of `|` separated flags")
             }
 
             fn visit_str<E: Error>(self, flags: &str) -> Result<Self::Value, E> {
-                flags.parse().map_err(|e| E::custom(e))
+                parser::from_str(flags).map_err(|e| E::custom(e))
             }
         }
 
         deserializer.deserialize_str(FlagsVisitor(Default::default()))
     } else {
         // Deserialize non-human-readable flags directly from the underlying bits
-        let bits = B::deserialize(deserializer)?;
+        let bits = B::Bits::deserialize(deserializer)?;
 
-        Ok(bits.into())
+        Ok(B::from_bits_retain(bits))
     }
 }
 
diff --git a/src/internal.rs b/src/internal.rs
index eca0a30..c4fb653 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -10,29 +10,14 @@
 #[doc(hidden)]
 macro_rules! __declare_internal_bitflags {
     (
-        $vis:vis struct $InternalBitFlags:ident: $T:ty;
-        $iter_vis:vis struct $Iter:ident;
-        $iter_names_vis:vis struct $IterNames:ident;
+        $vis:vis struct $InternalBitFlags:ident: $T:ty
     ) => {
         // NOTE: The ABI of this type is _guaranteed_ to be the same as `T`
         // This is relied on by some external libraries like `bytemuck` to make
         // its `unsafe` trait impls sound.
         #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
         #[repr(transparent)]
-        $vis struct $InternalBitFlags {
-            bits: $T,
-        }
-
-        $iter_vis struct $Iter {
-            inner: $IterNames,
-            done: bool,
-        }
-
-        $iter_names_vis struct $IterNames {
-            idx: usize,
-            source: $InternalBitFlags,
-            state: $InternalBitFlags,
-        }
+        $vis struct $InternalBitFlags($T);
     };
 }
 
@@ -44,14 +29,18 @@
 #[doc(hidden)]
 macro_rules! __impl_internal_bitflags {
     (
-        $InternalBitFlags:ident: $T:ty, $BitFlags:ident, $Iter:ident, $IterNames:ident {
+        $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $Flag:ident = $value:expr;
             )*
         }
     ) => {
-        impl $crate::__private::PublicFlags for $BitFlags {
+        // NOTE: This impl is also used to prevent using bits types from non-primitive types
+        // in the `bitflags` macro. If this approach is changed, this guard will need to be
+        // retained somehow
+        impl $crate::__private::PublicFlags for $PublicBitFlags {
+            type Primitive = $T;
             type Internal = $InternalBitFlags;
         }
 
@@ -73,7 +62,7 @@
                     // We can remove this `0x0` and remain compatible with `FromStr`,
                     // because an empty string will still parse to an empty set of flags,
                     // just like `0x0` does.
-                    $crate::__private::core::write!(f, "{:#x}", <$T as $crate::__private::Bits>::EMPTY)
+                    $crate::__private::core::write!(f, "{:#x}", <$T as $crate::Bits>::EMPTY)
                 } else {
                     $crate::__private::core::fmt::Display::fmt(self, f)
                 }
@@ -82,278 +71,21 @@
 
         impl $crate::__private::core::fmt::Display for $InternalBitFlags {
             fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter<'_>) -> $crate::__private::core::fmt::Result {
-                // A formatter for bitflags that produces text output like:
-                //
-                // A | B | 0xf6
-                //
-                // The names of set flags are written in a bar-separated-format,
-                // followed by a hex number of any remaining bits that are set
-                // but don't correspond to any flags.
-
-                // Iterate over the valid flags
-                let mut first = true;
-                let mut iter = self.iter_names();
-                for (name, _) in &mut iter {
-                    if !first {
-                        f.write_str(" | ")?;
-                    }
-
-                    first = false;
-                    f.write_str(name)?;
-                }
-
-                // Append any extra bits that correspond to flags to the end of the format
-                let extra_bits = iter.state.bits();
-                if extra_bits != <$T as $crate::__private::Bits>::EMPTY {
-                    if !first {
-                        f.write_str(" | ")?;
-                    }
-
-                    $crate::__private::core::write!(f, "{:#x}", extra_bits)?;
-                }
-
-                $crate::__private::core::fmt::Result::Ok(())
+                $crate::parser::to_writer(&$PublicBitFlags(*self), f)
             }
         }
 
-        // The impl for `FromStr` should parse anything produced by `Display`
         impl $crate::__private::core::str::FromStr for $InternalBitFlags {
             type Err = $crate::parser::ParseError;
 
             fn from_str(s: &str) -> $crate::__private::core::result::Result<Self, Self::Err> {
-                let s = s.trim();
-
-                let mut parsed_flags = Self::empty();
-
-                // If the input is empty then return an empty set of flags
-                if s.is_empty() {
-                    return $crate::__private::core::result::Result::Ok(parsed_flags);
-                }
-
-                for flag in s.split('|') {
-                    let flag = flag.trim();
-
-                    // If the flag is empty then we've got missing input
-                    if flag.is_empty() {
-                        return $crate::__private::core::result::Result::Err($crate::parser::ParseError::empty_flag());
-                    }
-
-                    // If the flag starts with `0x` then it's a hex number
-                    // Parse it directly to the underlying bits type
-                    let parsed_flag = if let $crate::__private::core::option::Option::Some(flag) = flag.strip_prefix("0x") {
-                        let bits = <$T>::from_str_radix(flag, 16).map_err(|_| $crate::parser::ParseError::invalid_hex_flag(flag))?;
-
-                        Self::from_bits_retain(bits)
-                    }
-                    // Otherwise the flag is a name
-                    // The generated flags type will determine whether
-                    // or not it's a valid identifier
-                    else {
-                        Self::from_name(flag).ok_or_else(|| $crate::parser::ParseError::invalid_named_flag(flag))?
-                    };
-
-                    parsed_flags.insert(parsed_flag);
-                }
-
-                $crate::__private::core::result::Result::Ok(parsed_flags)
-            }
-        }
-
-        impl $crate::__private::core::fmt::Binary for $InternalBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::Binary::fmt(&self.bits(), f)
-            }
-        }
-
-        impl $crate::__private::core::fmt::Octal for $InternalBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::Octal::fmt(&self.bits(), f)
-            }
-        }
-
-        impl $crate::__private::core::fmt::LowerHex for $InternalBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::LowerHex::fmt(&self.bits(), f)
-            }
-        }
-
-        impl $crate::__private::core::fmt::UpperHex for $InternalBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::UpperHex::fmt(&self.bits(), f)
-            }
-        }
-
-        impl $InternalBitFlags {
-            #[inline]
-            pub const fn empty() -> Self {
-                Self { bits: <$T as $crate::__private::Bits>::EMPTY }
-            }
-
-            #[inline]
-            pub const fn all() -> Self {
-                Self::from_bits_truncate(<$T as $crate::__private::Bits>::ALL)
-            }
-
-            #[inline]
-            pub const fn bits(&self) -> $T {
-                self.bits
-            }
-
-            #[inline]
-            pub fn bits_mut(&mut self) -> &mut $T {
-                &mut self.bits
-            }
-
-            #[inline]
-            pub const fn from_bits(bits: $T) -> $crate::__private::core::option::Option<Self> {
-                let truncated = Self::from_bits_truncate(bits).bits;
-
-                if truncated == bits {
-                    $crate::__private::core::option::Option::Some(Self { bits })
-                } else {
-                    $crate::__private::core::option::Option::None
-                }
-            }
-
-            #[inline]
-            pub const fn from_bits_truncate(bits: $T) -> Self {
-                if bits == <$T as $crate::__private::Bits>::EMPTY {
-                    return Self { bits }
-                }
-
-                let mut truncated = <$T as $crate::__private::Bits>::EMPTY;
-
-                $(
-                    __expr_safe_flags!(
-                        $(#[$attr $($args)*])*
-                        {
-                            if bits & $BitFlags::$Flag.bits() == $BitFlags::$Flag.bits() {
-                                truncated |= $BitFlags::$Flag.bits()
-                            }
-                        }
-                    );
-                )*
-
-                Self { bits: truncated }
-            }
-
-            #[inline]
-            pub const fn from_bits_retain(bits: $T) -> Self {
-                Self { bits }
-            }
-
-            #[inline]
-            pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> {
-                $(
-                    __expr_safe_flags!(
-                        $(#[$attr $($args)*])*
-                        {
-                            if name == $crate::__private::core::stringify!($Flag) {
-                                return $crate::__private::core::option::Option::Some(Self { bits: $BitFlags::$Flag.bits() });
-                            }
-                        }
-                    );
-                )*
-
-                let _ = name;
-                $crate::__private::core::option::Option::None
-            }
-
-            #[inline]
-            pub const fn iter(&self) -> $Iter {
-                $Iter {
-                    inner: self.iter_names(),
-                    done: false,
-                }
-            }
-
-            #[inline]
-            pub const fn iter_names(&self) -> $IterNames {
-                $IterNames {
-                    idx: 0,
-                    source: *self,
-                    state: *self,
-                }
-            }
-
-            #[inline]
-            pub const fn is_empty(&self) -> bool {
-                self.bits == Self::empty().bits
-            }
-
-            #[inline]
-            pub const fn is_all(&self) -> bool {
-                Self::all().bits | self.bits == self.bits
-            }
-
-            #[inline]
-            pub const fn intersects(&self, other: Self) -> bool {
-                !(Self { bits: self.bits & other.bits}).is_empty()
-            }
-
-            #[inline]
-            pub const fn contains(&self, other: Self) -> bool {
-                (self.bits & other.bits) == other.bits
-            }
-
-            #[inline]
-            pub fn insert(&mut self, other: Self) {
-                self.bits |= other.bits;
-            }
-
-            #[inline]
-            pub fn remove(&mut self, other: Self) {
-                self.bits &= !other.bits;
-            }
-
-            #[inline]
-            pub fn toggle(&mut self, other: Self) {
-                self.bits ^= other.bits;
-            }
-
-            #[inline]
-            pub fn set(&mut self, other: Self, value: bool) {
-                if value {
-                    self.insert(other);
-                } else {
-                    self.remove(other);
-                }
-            }
-
-            #[inline]
-            #[must_use]
-            pub const fn intersection(self, other: Self) -> Self {
-                Self { bits: self.bits & other.bits }
-            }
-
-            #[inline]
-            #[must_use]
-            pub const fn union(self, other: Self) -> Self {
-                Self { bits: self.bits | other.bits }
-            }
-
-            #[inline]
-            #[must_use]
-            pub const fn difference(self, other: Self) -> Self {
-                Self { bits: self.bits & !other.bits }
-            }
-
-            #[inline]
-            #[must_use]
-            pub const fn symmetric_difference(self, other: Self) -> Self {
-                Self { bits: self.bits ^ other.bits }
-            }
-
-            #[inline]
-            #[must_use]
-            pub const fn complement(self) -> Self {
-                Self::from_bits_truncate(!self.bits)
+                $crate::parser::from_str::<$PublicBitFlags>(s).map(|flags| flags.0)
             }
         }
 
         impl $crate::__private::core::convert::AsRef<$T> for $InternalBitFlags {
             fn as_ref(&self) -> &$T {
-                &self.bits
+                &self.0
             }
         }
 
@@ -363,208 +95,27 @@
             }
         }
 
-        impl $crate::__private::core::iter::Iterator for $Iter {
-            type Item = $BitFlags;
+        // The internal flags type offers a similar API to the public one
 
-            fn next(&mut self) -> $crate::__private::core::option::Option<Self::Item> {
-                match self.inner.next().map(|(_, value)| value) {
-                    $crate::__private::core::option::Option::Some(value) => $crate::__private::core::option::Option::Some(value),
-                    $crate::__private::core::option::Option::None if !self.done => {
-                        self.done = true;
-
-                        // After iterating through valid names, if there are any bits left over
-                        // then return one final value that includes them. This makes `into_iter`
-                        // and `from_iter` roundtrip
-                        if self.inner.state != $InternalBitFlags::empty() {
-                            $crate::__private::core::option::Option::Some($BitFlags::from_bits_retain(self.inner.state.bits()))
-                        } else {
-                            $crate::__private::core::option::Option::None
-                        }
-                    },
-                    _ => $crate::__private::core::option::Option::None,
-                }
+        __impl_public_bitflags! {
+            $InternalBitFlags: $T, $PublicBitFlags {
+                $(
+                    $(#[$attr $($args)*])*
+                    $Flag;
+                )*
             }
         }
 
-        impl $crate::__private::core::iter::Iterator for $IterNames {
-            type Item = (&'static str, $BitFlags);
+        __impl_public_bitflags_iter! {
+            $InternalBitFlags: $T, $PublicBitFlags
+        }
 
-            fn next(&mut self) -> $crate::__private::core::option::Option<Self::Item> {
-                const NUM_FLAGS: usize = {
-                    let mut num_flags = 0;
-
-                    $(
-                        __expr_safe_flags!(
-                            $(#[$attr $($args)*])*
-                            {
-                                { num_flags += 1; }
-                            }
-                        );
-                    )*
-
-                    num_flags
-                };
-
-                const OPTIONS: [$T; NUM_FLAGS] = [
-                    $(
-                        __expr_safe_flags!(
-                            $(#[$attr $($args)*])*
-                            {
-                                $BitFlags::$Flag.bits()
-                            }
-                        ),
-                    )*
-                ];
-
-                const OPTIONS_NAMES: [&'static str; NUM_FLAGS] = [
-                    $(
-                        __expr_safe_flags!(
-                            $(#[$attr $($args)*])*
-                            {
-                                $crate::__private::core::stringify!($Flag)
-                            }
-                        ),
-                    )*
-                ];
-
-                if self.state.is_empty() || NUM_FLAGS == 0 {
-                    $crate::__private::core::option::Option::None
-                } else {
-                    #[allow(clippy::indexing_slicing)]
-                    for (flag, flag_name) in OPTIONS[self.idx..NUM_FLAGS].iter().copied()
-                        .zip(OPTIONS_NAMES[self.idx..NUM_FLAGS].iter().copied())
-                    {
-                        self.idx += 1;
-
-                        // NOTE: We check whether the flag exists in self, but remove it from
-                        // a different value. This ensure that overlapping flags are handled
-                        // properly. Take the following example:
-                        //
-                        // const A: 0b00000001;
-                        // const B: 0b00000101;
-                        //
-                        // Given the bits 0b00000101, both A and B are set. But if we removed A
-                        // as we encountered it we'd be left with 0b00000100, which doesn't
-                        // correspond to a valid flag on its own.
-                        if self.source.contains($InternalBitFlags { bits: flag }) {
-                            self.state.remove($InternalBitFlags { bits: flag });
-
-                            return $crate::__private::core::option::Option::Some((flag_name, $BitFlags::from_bits_retain(flag)))
-                        }
-                    }
-
-                    $crate::__private::core::option::Option::None
-                }
+        impl $InternalBitFlags {
+            /// Returns a mutable reference to the raw value of the flags currently stored.
+            #[inline]
+            pub fn bits_mut(&mut self) -> &mut $T {
+                &mut self.0
             }
         }
     };
 }
-
-/// A macro that processed the input to `bitflags!` and shuffles attributes around
-/// based on whether or not they're "expression-safe".
-///
-/// This macro is a token-tree muncher that works on 2 levels:
-///
-/// For each attribute, we explicitly match on its identifier, like `cfg` to determine
-/// whether or not it should be considered expression-safe.
-///
-/// If you find yourself with an attribute that should be considered expression-safe
-/// and isn't, it can be added here.
-#[macro_export(local_inner_macros)]
-#[doc(hidden)]
-macro_rules! __expr_safe_flags {
-    // Entrypoint: Move all flags and all attributes into `unprocessed` lists
-    // where they'll be munched one-at-a-time
-    (
-        $(#[$inner:ident $($args:tt)*])*
-        { $e:expr }
-    ) => {
-        __expr_safe_flags! {
-            expr: { $e },
-            attrs: {
-                // All attributes start here
-                unprocessed: [$(#[$inner $($args)*])*],
-                processed: {
-                    // Attributes that are safe on expressions go here
-                    expr: [],
-                },
-            },
-        }
-    };
-    // Process the next attribute on the current flag
-    // `cfg`: The next flag should be propagated to expressions
-    // NOTE: You can copy this rules block and replace `cfg` with
-    // your attribute name that should be considered expression-safe
-    (
-        expr: { $e:expr },
-            attrs: {
-            unprocessed: [
-                // cfg matched here
-                #[cfg $($args:tt)*]
-                $($attrs_rest:tt)*
-            ],
-            processed: {
-                expr: [$($expr:tt)*],
-            },
-        },
-    ) => {
-        __expr_safe_flags! {
-            expr: { $e },
-            attrs: {
-                unprocessed: [
-                    $($attrs_rest)*
-                ],
-                processed: {
-                    expr: [
-                        $($expr)*
-                        // cfg added here
-                        #[cfg $($args)*]
-                    ],
-                },
-            },
-        }
-    };
-    // Process the next attribute on the current flag
-    // `$other`: The next flag should not be propagated to expressions
-    (
-        expr: { $e:expr },
-            attrs: {
-            unprocessed: [
-                // $other matched here
-                #[$other:ident $($args:tt)*]
-                $($attrs_rest:tt)*
-            ],
-            processed: {
-                expr: [$($expr:tt)*],
-            },
-        },
-    ) => {
-        __expr_safe_flags! {
-            expr: { $e },
-                attrs: {
-                unprocessed: [
-                    $($attrs_rest)*
-                ],
-                processed: {
-                    expr: [
-                        // $other not added here
-                        $($expr)*
-                    ],
-                },
-            },
-        }
-    };
-    // Once all attributes on all flags are processed, generate the actual code
-    (
-        expr: { $e:expr },
-        attrs: {
-            unprocessed: [],
-            processed: {
-                expr: [$(#[$expr:ident $($exprargs:tt)*])*],
-            },
-        },
-    ) => {
-        $(#[$expr $($exprargs)*])*
-        { $e }
-    }
-}
diff --git a/src/iter.rs b/src/iter.rs
new file mode 100644
index 0000000..4b6210e
--- /dev/null
+++ b/src/iter.rs
@@ -0,0 +1,133 @@
+//! Iterating over set flag values.
+
+use crate::{Flags, Flag};
+
+/// An iterator over a set of flags.
+///
+/// Any bits that don't correspond to a valid flag will be yielded
+/// as a final item from the iterator.
+pub struct Iter<B: 'static> {
+    inner: IterNames<B>,
+    done: bool,
+}
+
+impl<B: Flags> Iter<B> {
+    /// Create a new iterator over the given set of flags.
+    pub(crate) fn new(flags: &B) -> Self {
+        Iter {
+            inner: IterNames::new(flags),
+            done: false,
+        }
+    }
+}
+
+impl<B: 'static> Iter<B> {
+    #[doc(hidden)]
+    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, state: B) -> Self {
+        Iter {
+            inner: IterNames::__private_const_new(flags, source, state),
+            done: false,
+        }
+    }
+}
+
+impl<B: Flags> Iterator for Iter<B> {
+    type Item = B;
+    
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.inner.next() {
+            Some((_, flag)) => Some(flag),
+            None if !self.done => {
+                self.done = true;
+                
+                // After iterating through valid names, if there are any bits left over
+                // then return one final value that includes them. This makes `into_iter`
+                // and `from_iter` roundtrip
+                if !self.inner.remaining().is_empty() {
+                    Some(B::from_bits_retain(self.inner.state.bits()))
+                } else {
+                    None
+                }
+            }
+            None => None,
+        }
+    }
+}
+
+/// An iterator over a set of flags and their names.
+///
+/// Any bits that don't correspond to a valid flag will be ignored.
+pub struct IterNames<B: 'static> {
+    flags: &'static [Flag<B>],
+    idx: usize,
+    source: B,
+    state: B,
+}
+
+impl<B: Flags> IterNames<B> {
+    /// Create a new iterator over the given set of flags.
+    pub(crate) fn new(flags: &B) -> Self {
+        IterNames {
+            flags: B::FLAGS,
+            idx: 0,
+            state: B::from_bits_retain(flags.bits()),
+            source: B::from_bits_retain(flags.bits()),
+        }
+    }
+}
+
+impl<B: 'static> IterNames<B> {
+    #[doc(hidden)]
+    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, state: B) -> Self {
+        IterNames {
+            flags,
+            idx: 0,
+            state,
+            source,
+        }
+    }
+
+    /// Get the remaining (unyielded) flags.
+    ///
+    /// Once the iterator has finished, this method can be used to
+    /// check whether or not there are any bits that didn't correspond
+    /// to a valid flag remaining.
+    pub fn remaining(&self) -> &B {
+        &self.state
+    }
+}
+
+impl<B: Flags> Iterator for IterNames<B> {
+    type Item = (&'static str, B);
+    
+    fn next(&mut self) -> Option<Self::Item> {
+        while let Some(flag) = self.flags.get(self.idx) {
+            // Short-circuit if our state is empty
+            if self.state.is_empty() {
+                return None;
+            }
+
+            self.idx += 1;
+
+            let bits = flag.value().bits();
+
+            // NOTE: We check whether the flag exists in self, but remove it from
+            // a different value. This ensure that overlapping flags are handled
+            // properly. Take the following example:
+            //
+            // const A: 0b00000001;
+            // const B: 0b00000101;
+            //
+            // Given the bits 0b00000101, both A and B are set. But if we removed A
+            // as we encountered it we'd be left with 0b00000100, which doesn't
+            // correspond to a valid flag on its own.
+            if self.source.contains(B::from_bits_retain(bits)) {
+                self.state.remove(B::from_bits_retain(bits));
+
+                return Some((flag.name(), B::from_bits_retain(bits)));
+            }
+        }
+        
+        None
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 35eabca..37d5540 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -281,7 +281,7 @@
 //! use bitflags::bitflags;
 //! use std::{fmt, str};
 //!
-//! bitflags::bitflags! {
+//! bitflags! {
 //!     pub struct Flags: u32 {
 //!         const A = 1;
 //!         const B = 2;
@@ -374,16 +374,16 @@
 //! }
 //! ```
 //!
-//! [`from_bits`]: BitFlags::from_bits
-//! [`from_bits_truncate`]: BitFlags::from_bits_truncate
+//! [`from_bits`]: Flags::from_bits
+//! [`from_bits_truncate`]: Flags::from_bits_truncate
 //!
-//! # The `BitFlags` trait
+//! # The `Flags` trait
 //!
-//! This library defines a `BitFlags` trait that's implemented by all generated flags types.
+//! This library defines a `Flags` trait that's implemented by all generated flags types.
 //! The trait makes it possible to work with flags types generically:
 //!
 //! ```
-//! fn count_unset_flags<F: bitflags::BitFlags>(flags: &F) -> usize {
+//! fn count_unset_flags<F: bitflags::Flags>(flags: &F) -> usize {
 //!     // Find out how many flags there are in total
 //!     let total = F::all().iter().count();
 //!
@@ -423,22 +423,29 @@
 // ANDROID: Use std to allow building as a dylib.
 #![cfg_attr(not(any(feature = "std", test, android_dylib)), no_std)]
 #![cfg_attr(not(test), forbid(unsafe_code))]
-
-#![doc(html_root_url = "https://docs.rs/bitflags/2.2.1")]
+#![doc(html_root_url = "https://docs.rs/bitflags/2.3.2")]
 
 #[doc(inline)]
-pub use traits::BitFlags;
+pub use traits::{Flags, Flag, Bits};
 
+pub mod iter;
 pub mod parser;
+
 mod traits;
 
 #[doc(hidden)]
 pub mod __private {
-    pub use crate::{external::*, traits::*};
+    pub use crate::{external::__private::*, traits::__private::*};
 
     pub use core;
 }
 
+#[allow(unused_imports)]
+pub use external::*;
+
+#[allow(deprecated)]
+pub use traits::BitFlags;
+
 /*
 How does the bitflags crate work?
 
@@ -564,20 +571,14 @@
         // This type appears in the end-user's API
         __declare_public_bitflags! {
             $(#[$outer])*
-            $vis struct $BitFlags;
+            $vis struct $BitFlags
         }
 
         // Workaround for: https://github.com/bitflags/bitflags/issues/320
         __impl_public_bitflags_consts! {
-            $BitFlags {
+            $BitFlags: $T {
                 $(
                     $(#[$inner $($args)*])*
-                    #[allow(
-                        dead_code,
-                        deprecated,
-                        unused_attributes,
-                        non_upper_case_globals
-                    )]
                     $Flag = $value;
                 )*
             }
@@ -590,29 +591,28 @@
             unused_attributes,
             unused_mut,
             unused_imports,
-            non_upper_case_globals
+            non_upper_case_globals,
+            clippy::assign_op_pattern
         )]
         const _: () = {
             // Declared in a "hidden" scope that can't be reached directly
             // These types don't appear in the end-user's API
             __declare_internal_bitflags! {
-                $vis struct InternalBitFlags: $T;
-                $vis struct Iter;
-                $vis struct IterRaw;
+                $vis struct InternalBitFlags: $T
             }
 
             __impl_internal_bitflags! {
-                InternalBitFlags: $T, $BitFlags, Iter, IterRaw {
+                InternalBitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
-                        $Flag;
+                        $Flag = $value;
                     )*
                 }
             }
 
             // This is where new library trait implementations can be added
             __impl_external_bitflags! {
-                InternalBitFlags: $T {
+                InternalBitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
                         $Flag;
@@ -620,8 +620,60 @@
                 }
             }
 
+            __impl_public_bitflags_forward! {
+                $BitFlags: $T, InternalBitFlags
+            }
+
+            __impl_public_bitflags_iter! {
+                $BitFlags: $T, $BitFlags
+            }
+        };
+
+        bitflags! {
+            $($t)*
+        }
+    };
+    (
+        impl $BitFlags:ident: $T:ty {
+            $(
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:ident = $value:expr;
+            )*
+        }
+
+        $($t:tt)*
+    ) => {
+        __impl_public_bitflags_consts! {
+            $BitFlags: $T {
+                $(
+                    $(#[$inner $($args)*])*
+                    $Flag = $value;
+                )*
+            }
+        }
+
+        #[allow(
+            dead_code,
+            deprecated,
+            unused_doc_comments,
+            unused_attributes,
+            unused_mut,
+            unused_imports,
+            non_upper_case_globals,
+            clippy::assign_op_pattern
+        )]
+        const _: () = {
             __impl_public_bitflags! {
-                $BitFlags: $T, InternalBitFlags, Iter, IterRaw;
+                $BitFlags: $T, $BitFlags {
+                    $(
+                        $(#[$inner $($args)*])*
+                        $Flag;
+                    )*
+                }
+            }
+
+            __impl_public_bitflags_iter! {
+                $BitFlags: $T, $BitFlags
             }
         };
 
@@ -632,6 +684,357 @@
     () => {};
 }
 
+/// Implement functions on bitflags types.
+///
+/// We need to be careful about adding new methods and trait implementations here because they
+/// could conflict with items added by the end-user.
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __impl_bitflags {
+    (
+        $PublicBitFlags:ident: $T:ty {
+            fn empty() $empty:block
+            fn all() $all:block
+            fn bits($bits0:ident) $bits:block
+            fn from_bits($from_bits0:ident) $from_bits:block
+            fn from_bits_truncate($from_bits_truncate0:ident) $from_bits_truncate:block
+            fn from_bits_retain($from_bits_retain0:ident) $from_bits_retain:block
+            fn from_name($from_name0:ident) $from_name:block
+            fn is_empty($is_empty0:ident) $is_empty:block
+            fn is_all($is_all0:ident) $is_all:block
+            fn intersects($intersects0:ident, $intersects1:ident) $intersects:block
+            fn contains($contains0:ident, $contains1:ident) $contains:block
+            fn insert($insert0:ident, $insert1:ident) $insert:block
+            fn remove($remove0:ident, $remove1:ident) $remove:block
+            fn toggle($toggle0:ident, $toggle1:ident) $toggle:block
+            fn set($set0:ident, $set1:ident, $set2:ident) $set:block
+            fn intersection($intersection0:ident, $intersection1:ident) $intersection:block
+            fn union($union0:ident, $union1:ident) $union:block
+            fn difference($difference0:ident, $difference1:ident) $difference:block
+            fn symmetric_difference($symmetric_difference0:ident, $symmetric_difference1:ident) $symmetric_difference:block
+            fn complement($complement0:ident) $complement:block
+        }
+    ) => {
+        #[allow(
+            dead_code,
+            deprecated,
+            unused_attributes
+        )]
+        impl $PublicBitFlags {
+            /// Returns an empty set of flags.
+            #[inline]
+            pub const fn empty() -> Self {
+                $empty
+            }
+
+            /// Returns the set containing all flags.
+            #[inline]
+            pub const fn all() -> Self {
+                $all
+            }
+
+            /// Returns the raw value of the flags currently stored.
+            #[inline]
+            pub const fn bits(&self) -> $T {
+                let $bits0 = self;
+                $bits
+            }
+
+            /// 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::__private::core::option::Option<Self> {
+                let $from_bits0 = bits;
+                $from_bits
+            }
+
+            /// Convert from underlying bit representation, dropping any bits
+            /// that do not correspond to flags.
+            #[inline]
+            pub const fn from_bits_truncate(bits: $T) -> Self {
+                let $from_bits_truncate0 = bits;
+                $from_bits_truncate
+            }
+
+            /// Convert from underlying bit representation, preserving all
+            /// bits (even those not corresponding to a defined flag).
+            #[inline]
+            pub const fn from_bits_retain(bits: $T) -> Self {
+                let $from_bits_retain0 = bits;
+                $from_bits_retain
+            }
+
+            /// Get the value for a flag from its stringified name.
+            ///
+            /// Names are _case-sensitive_, so must correspond exactly to
+            /// the identifier given to the flag.
+            #[inline]
+            pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> {
+                let $from_name0 = name;
+                $from_name
+            }
+
+            /// Returns `true` if no flags are currently stored.
+            #[inline]
+            pub const fn is_empty(&self) -> bool {
+                let $is_empty0 = self;
+                $is_empty
+            }
+
+            /// Returns `true` if all flags are currently set.
+            #[inline]
+            pub const fn is_all(&self) -> bool {
+                let $is_all0 = self;
+                $is_all
+            }
+
+            /// Returns `true` if there are flags common to both `self` and `other`.
+            #[inline]
+            pub const fn intersects(&self, other: Self) -> bool {
+                let $intersects0 = self;
+                let $intersects1 = other;
+                $intersects
+            }
+
+            /// Returns `true` if all of the flags in `other` are contained within `self`.
+            #[inline]
+            pub const fn contains(&self, other: Self) -> bool {
+                let $contains0 = self;
+                let $contains1 = other;
+                $contains
+            }
+
+            /// Inserts the specified flags in-place.
+            #[inline]
+            pub fn insert(&mut self, other: Self) {
+                let $insert0 = self;
+                let $insert1 = other;
+                $insert
+            }
+
+            /// Removes the specified flags in-place.
+            #[inline]
+            pub fn remove(&mut self, other: Self) {
+                let $remove0 = self;
+                let $remove1 = other;
+                $remove
+            }
+
+            /// Toggles the specified flags in-place.
+            #[inline]
+            pub fn toggle(&mut self, other: Self) {
+                let $toggle0 = self;
+                let $toggle1 = other;
+                $toggle
+            }
+
+            /// Inserts or removes the specified flags depending on the passed value.
+            #[inline]
+            pub fn set(&mut self, other: Self, value: bool) {
+                let $set0 = self;
+                let $set1 = other;
+                let $set2 = value;
+                $set
+            }
+
+            /// Returns the intersection between the flags in `self` and
+            /// `other`.
+            ///
+            /// Specifically, the returned set contains only the flags which are
+            /// present in *both* `self` *and* `other`.
+            ///
+            /// This is equivalent to using the `&` operator (e.g.
+            /// [`ops::BitAnd`]), as in `flags & other`.
+            ///
+            /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
+            #[inline]
+            #[must_use]
+            pub const fn intersection(self, other: Self) -> Self {
+                let $intersection0 = self;
+                let $intersection1 = other;
+                $intersection
+            }
+
+            /// Returns the union of between the flags in `self` and `other`.
+            ///
+            /// Specifically, the returned set contains all flags which are
+            /// present in *either* `self` *or* `other`, including any which are
+            /// present in both (see [`Self::symmetric_difference`] if that
+            /// is undesirable).
+            ///
+            /// This is equivalent to using the `|` operator (e.g.
+            /// [`ops::BitOr`]), as in `flags | other`.
+            ///
+            /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
+            #[inline]
+            #[must_use]
+            pub const fn union(self, other: Self) -> Self {
+                let $union0 = self;
+                let $union1 = other;
+                $union
+            }
+
+            /// Returns the difference between the flags in `self` and `other`.
+            ///
+            /// Specifically, the returned set contains all flags present in
+            /// `self`, except for the ones present in `other`.
+            ///
+            /// It is also conceptually equivalent to the "bit-clear" operation:
+            /// `flags & !other` (and this syntax is also supported).
+            ///
+            /// This is equivalent to using the `-` operator (e.g.
+            /// [`ops::Sub`]), as in `flags - other`.
+            ///
+            /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
+            #[inline]
+            #[must_use]
+            pub const fn difference(self, other: Self) -> Self {
+                let $difference0 = self;
+                let $difference1 = other;
+                $difference
+            }
+
+            /// Returns the [symmetric difference][sym-diff] between the flags
+            /// in `self` and `other`.
+            ///
+            /// Specifically, the returned set contains the flags present which
+            /// are present in `self` or `other`, but that are not present in
+            /// both. Equivalently, it contains the flags present in *exactly
+            /// one* of the sets `self` and `other`.
+            ///
+            /// This is equivalent to using the `^` operator (e.g.
+            /// [`ops::BitXor`]), as in `flags ^ other`.
+            ///
+            /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
+            /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
+            #[inline]
+            #[must_use]
+            pub const fn symmetric_difference(self, other: Self) -> Self {
+                let $symmetric_difference0 = self;
+                let $symmetric_difference1 = other;
+                $symmetric_difference
+            }
+
+            /// Returns the complement of this set of flags.
+            ///
+            /// Specifically, the returned set contains all the flags which are
+            /// not set in `self`, but which are allowed for this type.
+            ///
+            /// Alternatively, it can be thought of as the set difference
+            /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`)
+            ///
+            /// This is equivalent to using the `!` operator (e.g.
+            /// [`ops::Not`]), as in `!flags`.
+            ///
+            /// [`Self::all()`]: Self::all
+            /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
+            #[inline]
+            #[must_use]
+            pub const fn complement(self) -> Self {
+                let $complement0 = self;
+                $complement
+            }
+        }
+    };
+}
+
+/// A macro that processed the input to `bitflags!` and shuffles attributes around
+/// based on whether or not they're "expression-safe".
+///
+/// This macro is a token-tree muncher that works on 2 levels:
+///
+/// For each attribute, we explicitly match on its identifier, like `cfg` to determine
+/// whether or not it should be considered expression-safe.
+///
+/// If you find yourself with an attribute that should be considered expression-safe
+/// and isn't, it can be added here.
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __bitflags_expr_safe_attrs {
+    // Entrypoint: Move all flags and all attributes into `unprocessed` lists
+    // where they'll be munched one-at-a-time
+    (
+        $(#[$inner:ident $($args:tt)*])*
+        { $e:expr }
+    ) => {
+        __bitflags_expr_safe_attrs! {
+            expr: { $e },
+            attrs: {
+                // All attributes start here
+                unprocessed: [$(#[$inner $($args)*])*],
+                // Attributes that are safe on expressions go here
+                processed: [],
+            },
+        }
+    };
+    // Process the next attribute on the current flag
+    // `cfg`: The next flag should be propagated to expressions
+    // NOTE: You can copy this rules block and replace `cfg` with
+    // your attribute name that should be considered expression-safe
+    (
+        expr: { $e:expr },
+            attrs: {
+            unprocessed: [
+                // cfg matched here
+                #[cfg $($args:tt)*]
+                $($attrs_rest:tt)*
+            ],
+            processed: [$($expr:tt)*],
+        },
+    ) => {
+        __bitflags_expr_safe_attrs! {
+            expr: { $e },
+            attrs: {
+                unprocessed: [
+                    $($attrs_rest)*
+                ],
+                processed: [
+                    $($expr)*
+                    // cfg added here
+                    #[cfg $($args)*]
+                ],
+            },
+        }
+    };
+    // Process the next attribute on the current flag
+    // `$other`: The next flag should not be propagated to expressions
+    (
+        expr: { $e:expr },
+            attrs: {
+            unprocessed: [
+                // $other matched here
+                #[$other:ident $($args:tt)*]
+                $($attrs_rest:tt)*
+            ],
+            processed: [$($expr:tt)*],
+        },
+    ) => {
+        __bitflags_expr_safe_attrs! {
+            expr: { $e },
+                attrs: {
+                unprocessed: [
+                    $($attrs_rest)*
+                ],
+                processed: [
+                    // $other not added here
+                    $($expr)*
+                ],
+            },
+        }
+    };
+    // Once all attributes on all flags are processed, generate the actual code
+    (
+        expr: { $e:expr },
+        attrs: {
+            unprocessed: [],
+            processed: [$(#[$expr:ident $($exprargs:tt)*])*],
+        },
+    ) => {
+        $(#[$expr $($exprargs)*])*
+        { $e }
+    }
+}
+
 #[macro_use]
 mod public;
 #[macro_use]
@@ -651,6 +1054,9 @@
         str,
     };
 
+    #[derive(Debug, PartialEq, Eq)]
+    pub struct ManualFlags(u32);
+
     bitflags! {
         #[doc = "> The first principle is that you must not fool yourself — and"]
         #[doc = "> you are the easiest person to fool."]
@@ -687,6 +1093,17 @@
         struct LongFlags: u32 {
             const LONG_A = 0b1111111111111111;
         }
+
+        impl ManualFlags: u32 {
+            const A = 0b00000001;
+            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
+            const B = 0b00000010;
+            const C = 0b00000100;
+            #[doc = "* cmr bed"]
+            #[doc = "* strcat table"]
+            #[doc = "<strcat> wait what?"]
+            const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+        }
     }
 
     bitflags! {
@@ -725,6 +1142,8 @@
         assert_eq!(Flags::A.bits(), 0b00000001);
         assert_eq!(Flags::ABC.bits(), 0b00000111);
 
+        assert_eq!(<Flags as crate::Flags>::bits(&Flags::ABC), 0b00000111);
+
         assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
         assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
 
@@ -739,6 +1158,8 @@
         assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B));
         assert_eq!(Flags::from_bits(0b1000), None);
 
+        assert_eq!(<Flags as crate::Flags>::from_bits(0b11), Some(Flags::A | Flags::B));
+
         assert_eq!(
             AnotherSetOfFlags::from_bits(!0_i8),
             Some(AnotherSetOfFlags::ANOTHER_FLAG)
@@ -757,6 +1178,8 @@
         assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty());
         assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A);
 
+        assert_eq!(<Flags as crate::Flags>::from_bits_truncate(0b11), (Flags::A | Flags::B));
+
         assert_eq!(
             AnotherSetOfFlags::from_bits_truncate(0_i8),
             AnotherSetOfFlags::empty()
@@ -777,6 +1200,8 @@
         assert_eq!(Flags::from_bits_retain(0b1000), (extra | Flags::empty()));
         assert_eq!(Flags::from_bits_retain(0b1001), (extra | Flags::A));
 
+        assert_eq!(<Flags as crate::Flags>::from_bits_retain(0b11), (Flags::A | Flags::B));
+
         let extra = EmptyFlags::from_bits_retain(0b1000);
         assert_eq!(
             EmptyFlags::from_bits_retain(0b1000),
@@ -790,6 +1215,8 @@
         assert!(!Flags::A.is_empty());
         assert!(!Flags::ABC.is_empty());
 
+        assert!(!<Flags as crate::Flags>::is_empty(&Flags::ABC));
+
         assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
 
         assert!(EmptyFlags::empty().is_empty());
@@ -807,6 +1234,8 @@
         assert!(!(Flags::A | extra).is_all());
         assert!((Flags::ABC | extra).is_all());
 
+        assert!(<Flags as crate::Flags>::is_all(&Flags::all()));
+
         assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
 
         assert!(EmptyFlags::all().is_all());
@@ -819,6 +1248,8 @@
         let e2 = Flags::empty();
         assert!(!e1.intersects(e2));
 
+        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
+
         assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG));
     }
 
@@ -827,6 +1258,8 @@
         let e1 = Flags::empty();
         let e2 = Flags::ABC;
         assert!(!e1.intersects(e2));
+
+        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
     }
 
     #[test]
@@ -834,6 +1267,8 @@
         let e1 = Flags::A;
         let e2 = Flags::B;
         assert!(!e1.intersects(e2));
+
+        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
     }
 
     #[test]
@@ -841,6 +1276,8 @@
         let e1 = Flags::A;
         let e2 = Flags::A | Flags::B;
         assert!(e1.intersects(e2));
+
+        assert!(<Flags as crate::Flags>::intersects(&e1, e2));
     }
 
     #[test]
@@ -851,6 +1288,8 @@
         assert!(e2.contains(e1));
         assert!(Flags::ABC.contains(e2));
 
+        assert!(<Flags as crate::Flags>::contains(&Flags::ABC, e2));
+
         assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
 
         assert!(EmptyFlags::empty().contains(EmptyFlags::empty()));
@@ -863,6 +1302,11 @@
         e1.insert(e2);
         assert_eq!(e1, e2);
 
+        let mut e1 = Flags::A;
+        let e2 = Flags::A | Flags::B;
+        <Flags as crate::Flags>::insert(&mut e1, e2);
+        assert_eq!(e1, e2);
+
         let mut e3 = AnotherSetOfFlags::empty();
         e3.insert(AnotherSetOfFlags::ANOTHER_FLAG);
         assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG);
@@ -875,6 +1319,11 @@
         e1.remove(e2);
         assert_eq!(e1, Flags::B);
 
+        let mut e1 = Flags::A | Flags::B;
+        let e2 = Flags::A | Flags::C;
+        <Flags as crate::Flags>::remove(&mut e1, e2);
+        assert_eq!(e1, Flags::B);
+
         let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG;
         e3.remove(AnotherSetOfFlags::ANOTHER_FLAG);
         assert_eq!(e3, AnotherSetOfFlags::empty());
@@ -927,6 +1376,8 @@
         assert_eq!(ac, Flags::C.union(Flags::A));
         assert_eq!(bc, Flags::C.union(Flags::B));
 
+        assert_eq!(ac, <Flags as crate::Flags>::union(Flags::A, Flags::C));
+
         assert_eq!(ac, Flags::A | Flags::C);
         assert_eq!(bc, Flags::B | Flags::C);
         assert_eq!(ab.union(bc), Flags::ABC);
@@ -942,15 +1393,24 @@
         assert_eq!(ac.intersection(bc), Flags::C);
         assert_eq!(bc.intersection(ac), Flags::C);
 
+        assert_eq!(Flags::C, <Flags as crate::Flags>::intersection(ac, bc));
+
         assert_eq!(ac.difference(bc), ac - bc);
         assert_eq!(bc.difference(ac), bc - ac);
         assert_eq!(ac.difference(bc), Flags::A);
         assert_eq!(bc.difference(ac), Flags::B);
 
+        assert_eq!(bc, <Flags as crate::Flags>::difference(bc, Flags::A));
+
         assert_eq!(bc.complement(), !bc);
         assert_eq!(bc.complement(), Flags::A);
+
+        assert_eq!(Flags::A, <Flags as crate::Flags>::complement(bc));
+
         assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B));
         assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B));
+
+        assert_eq!(ab, <Flags as crate::Flags>::symmetric_difference(ac, bc));
     }
 
     #[test]
@@ -1288,7 +1748,6 @@
         parse_case(FmtFlags::empty(), "");
         parse_case(FmtFlags::empty(), " \r\n\t");
         parse_case(FmtFlags::empty(), "0x0");
-        parse_case(FmtFlags::empty(), "0x0");
 
         parse_case(FmtFlags::고양이, "고양이");
         parse_case(FmtFlags::고양이, "  고양이  ");
diff --git a/src/parser.rs b/src/parser.rs
index 48f3c61..aac9042 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -28,7 +28,118 @@
 
 #![allow(clippy::let_unit_value)]
 
-use core::fmt;
+use core::fmt::{self, Write};
+
+use crate::{Flags, Bits};
+
+/// Write a set of flags to a writer.
+///
+/// Any bits that don't correspond to a valid flag will be formatted
+/// as a hex number.
+pub fn to_writer<B: Flags>(flags: &B, mut writer: impl Write) -> Result<(), fmt::Error>
+where
+    B::Bits: WriteHex,
+{
+    // A formatter for bitflags that produces text output like:
+    //
+    // A | B | 0xf6
+    //
+    // The names of set flags are written in a bar-separated-format,
+    // followed by a hex number of any remaining bits that are set
+    // but don't correspond to any flags.
+
+    // Iterate over the valid flags
+    let mut first = true;
+    let mut iter = flags.iter_names();
+    for (name, _) in &mut iter {
+        if !first {
+            writer.write_str(" | ")?;
+        }
+
+        first = false;
+        writer.write_str(name)?;
+    }
+
+    // Append any extra bits that correspond to flags to the end of the format
+    let remaining = iter.remaining().bits();
+    if remaining != B::Bits::EMPTY {
+        if !first {
+            writer.write_str(" | ")?;
+        }
+
+        writer.write_str("0x")?;
+        remaining.write_hex(writer)?;
+    }
+
+    fmt::Result::Ok(())
+}
+
+pub(crate) struct AsDisplay<'a, B>(pub(crate) &'a B);
+
+impl<'a, B: Flags> fmt::Display for AsDisplay<'a, B>
+where
+    B::Bits: WriteHex,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        to_writer(self.0, f)
+    }
+}
+
+/// Parse a set of flags from text.
+///
+/// This function will fail on unknown flags rather than ignore them.
+pub fn from_str<B: Flags>(input: &str) -> Result<B, ParseError>
+where
+    B::Bits: ParseHex,
+{
+    let mut parsed_flags = B::empty();
+
+    // If the input is empty then return an empty set of flags
+    if input.trim().is_empty() {
+        return Ok(parsed_flags);
+    }
+
+    for flag in input.split('|') {
+        let flag = flag.trim();
+
+        // If the flag is empty then we've got missing input
+        if flag.is_empty() {
+            return Err(ParseError::empty_flag());
+        }
+
+        // If the flag starts with `0x` then it's a hex number
+        // Parse it directly to the underlying bits type
+        let parsed_flag = if let Some(flag) = flag.strip_prefix("0x") {
+            let bits = <B::Bits>::parse_hex(flag).map_err(|_| ParseError::invalid_hex_flag(flag))?;
+
+            B::from_bits_retain(bits)
+        }
+        // Otherwise the flag is a name
+        // The generated flags type will determine whether
+        // or not it's a valid identifier
+        else {
+            B::from_name(flag).ok_or_else(|| ParseError::invalid_named_flag(flag))?
+        };
+
+        parsed_flags.insert(parsed_flag);
+    }
+
+    Ok(parsed_flags)
+}
+
+/// Encode a value as a hex number.
+pub trait WriteHex {
+    /// Write the value as hex.
+    fn write_hex<W: fmt::Write>(&self, writer: W) -> fmt::Result;
+}
+
+/// Parse a value from a number encoded as a hex string.
+pub trait ParseHex {
+    /// Parse the value from hex.
+    fn parse_hex(input: &str) -> Result<Self, ParseError>
+    where
+        Self: Sized;
+}
 
 /// An error encountered while parsing flags from text.
 #[derive(Debug)]
diff --git a/src/public.rs b/src/public.rs
index 643f843..57ab0ea 100644
--- a/src/public.rs
+++ b/src/public.rs
@@ -11,10 +11,114 @@
 macro_rules! __declare_public_bitflags {
     (
         $(#[$outer:meta])*
-        $vis:vis struct $BitFlags:ident;
+        $vis:vis struct $PublicBitFlags:ident
     ) => {
         $(#[$outer])*
-        $vis struct $BitFlags(<$BitFlags as $crate::__private::PublicFlags>::Internal);
+        $vis struct $PublicBitFlags(<$PublicBitFlags as $crate::__private::PublicFlags>::Internal);
+    };
+}
+
+/// Implement functions on the public (user-facing) bitflags type.
+///
+/// We need to be careful about adding new methods and trait implementations here because they
+/// could conflict with items added by the end-user.
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __impl_public_bitflags_forward {
+    (
+        $PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident
+    ) => {
+        __impl_bitflags! {
+            $PublicBitFlags: $T {
+                fn empty() {
+                    Self($InternalBitFlags::empty())
+                }
+
+                fn all() {
+                    Self($InternalBitFlags::all())
+                }
+
+                fn bits(f) {
+                    f.0.bits()
+                }
+
+                fn from_bits(bits) {
+                    match $InternalBitFlags::from_bits(bits) {
+                        $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)),
+                        $crate::__private::core::option::Option::None => $crate::__private::core::option::Option::None,
+                    }
+                }
+
+                fn from_bits_truncate(bits) {
+                    Self($InternalBitFlags::from_bits_truncate(bits))
+                }
+
+                fn from_bits_retain(bits) {
+                    Self($InternalBitFlags::from_bits_retain(bits))
+                }
+
+                fn from_name(name) {
+                    match $InternalBitFlags::from_name(name) {
+                        $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)),
+                        $crate::__private::core::option::Option::None => $crate::__private::core::option::Option::None,
+                    }
+                }
+
+                fn is_empty(f) {
+                    f.0.is_empty()
+                }
+
+                fn is_all(f) {
+                    f.0.is_all()
+                }
+
+                fn intersects(f, other) {
+                    f.0.intersects(other.0)
+                }
+
+                fn contains(f, other) {
+                    f.0.contains(other.0)
+                }
+
+                fn insert(f, other) {
+                    f.0.insert(other.0)
+                }
+
+                fn remove(f, other) {
+                    f.0.remove(other.0)
+                }
+
+                fn toggle(f, other) {
+                    f.0.toggle(other.0)
+                }
+
+                fn set(f, other, value) {
+                    f.0.set(other.0, value)
+                }
+
+                fn intersection(f, other) {
+                    Self(f.0.intersection(other.0))
+                }
+
+                fn union(f, other) {
+                    Self(f.0.union(other.0))
+                }
+
+                fn difference(f, other) {
+                    Self(f.0.difference(other.0))
+                }
+
+                fn symmetric_difference(f, other) {
+                    Self(f.0.symmetric_difference(other.0))
+                }
+
+                fn complement(f) {
+                    Self(f.0.complement())
+                }
+            }
+        }
+
+        __impl_public_bitflags_ops!($PublicBitFlags);
     };
 }
 
@@ -26,8 +130,175 @@
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags {
     (
-        $PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident, $Iter:ident, $IterNames:ident;
+        $BitFlags:ident: $T:ty, $PublicBitFlags:ident {
+            $(
+                $(#[$attr:ident $($args:tt)*])*
+                $Flag:ident;
+            )*
+        }
     ) => {
+        __impl_bitflags! {
+            $BitFlags: $T {
+                fn empty() {
+                    Self(<$T as $crate::Bits>::EMPTY)
+                }
+
+                fn all() {
+                    Self::from_bits_truncate(<$T as $crate::Bits>::ALL)
+                }
+
+                fn bits(f) {
+                    f.0
+                }
+
+                fn from_bits(bits) {
+                    let truncated = Self::from_bits_truncate(bits).0;
+
+                    if truncated == bits {
+                        $crate::__private::core::option::Option::Some(Self(bits))
+                    } else {
+                        $crate::__private::core::option::Option::None
+                    }
+                }
+
+                fn from_bits_truncate(bits) {
+                    if bits == <$T as $crate::Bits>::EMPTY {
+                        return Self(bits)
+                    }
+
+                    let mut truncated = <$T as $crate::Bits>::EMPTY;
+
+                    $(
+                        __bitflags_expr_safe_attrs!(
+                            $(#[$attr $($args)*])*
+                            {
+                                if bits & $PublicBitFlags::$Flag.bits() == $PublicBitFlags::$Flag.bits() {
+                                    truncated = truncated | $PublicBitFlags::$Flag.bits()
+                                }
+                            }
+                        );
+                    )*
+
+                    Self(truncated)
+                }
+
+                fn from_bits_retain(bits) {
+                    Self(bits)
+                }
+
+                fn from_name(name) {
+                    $(
+                        __bitflags_expr_safe_attrs!(
+                            $(#[$attr $($args)*])*
+                            {
+                                if name == $crate::__private::core::stringify!($Flag) {
+                                    return $crate::__private::core::option::Option::Some(Self($PublicBitFlags::$Flag.bits()));
+                                }
+                            }
+                        );
+                    )*
+
+                    let _ = name;
+                    $crate::__private::core::option::Option::None
+                }
+
+                fn is_empty(f) {
+                    f.0 == Self::empty().0
+                }
+
+                fn is_all(f) {
+                    Self::all().0 | f.0 == f.0
+                }
+
+                fn intersects(f, other) {
+                    !(Self(f.0 & other.0)).is_empty()
+                }
+
+                fn contains(f, other) {
+                    (f.0 & other.0) == other.0
+                }
+
+                fn insert(f, other) {
+                    f.0 = f.0 | other.0;
+                }
+
+                fn remove(f, other) {
+                    f.0 = f.0 & !other.0;
+                }
+
+                fn toggle(f, other) {
+                    f.0 = f.0 ^ other.0;
+                }
+
+                fn set(f, other, value) {
+                    if value {
+                        f.insert(other);
+                    } else {
+                        f.remove(other);
+                    }
+                }
+
+                fn intersection(f, other) {
+                    Self(f.0 & other.0)
+                }
+
+                fn union(f, other) {
+                    Self(f.0 | other.0)
+                }
+
+                fn difference(f, other) {
+                    Self(f.0 & !other.0)
+                }
+
+                fn symmetric_difference(f, other) {
+                    Self(f.0 ^ other.0)
+                }
+
+                fn complement(f) {
+                    Self::from_bits_truncate(!f.0)
+                }
+            }
+        }
+
+        __impl_public_bitflags_ops!($BitFlags);
+    };
+}
+
+/// Implement iterators on the public (user-facing) bitflags type.
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __impl_public_bitflags_iter {
+    ($BitFlags:ident: $T:ty, $PublicBitFlags:ident) => {
+        impl $BitFlags {
+            /// Iterate over enabled flag values.
+            #[inline]
+            pub const fn iter(&self) -> $crate::iter::Iter<$PublicBitFlags> {
+                $crate::iter::Iter::__private_const_new(<$PublicBitFlags as $crate::Flags>::FLAGS, $PublicBitFlags::from_bits_retain(self.bits()), $PublicBitFlags::from_bits_retain(self.bits()))
+            }
+
+            /// Iterate over enabled flag values with their stringified names.
+            #[inline]
+            pub const fn iter_names(&self) -> $crate::iter::IterNames<$PublicBitFlags> {
+                $crate::iter::IterNames::__private_const_new(<$PublicBitFlags as $crate::Flags>::FLAGS, $PublicBitFlags::from_bits_retain(self.bits()), $PublicBitFlags::from_bits_retain(self.bits()))
+            }
+        }
+
+        impl $crate::__private::core::iter::IntoIterator for $BitFlags {
+            type Item = $PublicBitFlags;
+            type IntoIter = $crate::iter::Iter<$PublicBitFlags>;
+
+            fn into_iter(self) -> Self::IntoIter {
+                self.iter()
+            }
+        }
+    };
+}
+
+/// Implement traits on the public (user-facing) bitflags type.
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __impl_public_bitflags_ops {
+    ($PublicBitFlags:ident) => {
         impl $crate::__private::core::fmt::Binary for $PublicBitFlags {
             fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
                 $crate::__private::core::fmt::Binary::fmt(&self.0, f)
@@ -52,211 +323,6 @@
             }
         }
 
-        impl $PublicBitFlags {
-            /// Returns an empty set of flags.
-            #[inline]
-            pub const fn empty() -> Self {
-                Self($InternalBitFlags::empty())
-            }
-
-            /// Returns the set containing all flags.
-            #[inline]
-            pub const fn all() -> Self {
-                Self($InternalBitFlags::all())
-            }
-
-            /// Returns the raw value of the flags currently stored.
-            #[inline]
-            pub const fn bits(&self) -> $T {
-                self.0.bits()
-            }
-
-            /// 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::__private::core::option::Option<Self> {
-                match $InternalBitFlags::from_bits(bits) {
-                    $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)),
-                    $crate::__private::core::option::Option::None => $crate::__private::core::option::Option::None,
-                }
-            }
-
-            /// Convert from underlying bit representation, dropping any bits
-            /// that do not correspond to flags.
-            #[inline]
-            pub const fn from_bits_truncate(bits: $T) -> Self {
-                Self($InternalBitFlags::from_bits_truncate(bits))
-            }
-
-            /// Convert from underlying bit representation, preserving all
-            /// bits (even those not corresponding to a defined flag).
-            #[inline]
-            pub const fn from_bits_retain(bits: $T) -> Self {
-                Self($InternalBitFlags::from_bits_retain(bits))
-            }
-
-            /// Get the value for a flag from its stringified name.
-            ///
-            /// Names are _case-sensitive_, so must correspond exactly to
-            /// the identifier given to the flag.
-            #[inline]
-            pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> {
-                match $InternalBitFlags::from_name(name) {
-                    $crate::__private::core::option::Option::Some(bits) => $crate::__private::core::option::Option::Some(Self(bits)),
-                    $crate::__private::core::option::Option::None => $crate::__private::core::option::Option::None,
-                }
-            }
-
-            /// Iterate over enabled flag values.
-            #[inline]
-            pub const fn iter(&self) -> $Iter {
-                self.0.iter()
-            }
-
-            /// Iterate over enabled flag values with their stringified names.
-            #[inline]
-            pub const fn iter_names(&self) -> $IterNames {
-                self.0.iter_names()
-            }
-
-            /// Returns `true` if no flags are currently stored.
-            #[inline]
-            pub const fn is_empty(&self) -> bool {
-                self.0.is_empty()
-            }
-
-            /// Returns `true` if all flags are currently set.
-            #[inline]
-            pub const fn is_all(&self) -> bool {
-                self.0.is_all()
-            }
-
-            /// Returns `true` if there are flags common to both `self` and `other`.
-            #[inline]
-            pub const fn intersects(&self, other: Self) -> bool {
-                self.0.intersects(other.0)
-            }
-
-            /// Returns `true` if all of the flags in `other` are contained within `self`.
-            #[inline]
-            pub const fn contains(&self, other: Self) -> bool {
-                self.0.contains(other.0)
-            }
-
-            /// Inserts the specified flags in-place.
-            #[inline]
-            pub fn insert(&mut self, other: Self) {
-                self.0.insert(other.0)
-            }
-
-            /// Removes the specified flags in-place.
-            #[inline]
-            pub fn remove(&mut self, other: Self) {
-                self.0.remove(other.0)
-            }
-
-            /// Toggles the specified flags in-place.
-            #[inline]
-            pub fn toggle(&mut self, other: Self) {
-                self.0.toggle(other.0)
-            }
-
-            /// Inserts or removes the specified flags depending on the passed value.
-            #[inline]
-            pub fn set(&mut self, other: Self, value: bool) {
-                self.0.set(other.0, value)
-            }
-
-            /// Returns the intersection between the flags in `self` and
-            /// `other`.
-            ///
-            /// Specifically, the returned set contains only the flags which are
-            /// present in *both* `self` *and* `other`.
-            ///
-            /// This is equivalent to using the `&` operator (e.g.
-            /// [`ops::BitAnd`]), as in `flags & other`.
-            ///
-            /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
-            #[inline]
-            #[must_use]
-            pub const fn intersection(self, other: Self) -> Self {
-                Self(self.0.intersection(other.0))
-            }
-
-            /// Returns the union of between the flags in `self` and `other`.
-            ///
-            /// Specifically, the returned set contains all flags which are
-            /// present in *either* `self` *or* `other`, including any which are
-            /// present in both (see [`Self::symmetric_difference`] if that
-            /// is undesirable).
-            ///
-            /// This is equivalent to using the `|` operator (e.g.
-            /// [`ops::BitOr`]), as in `flags | other`.
-            ///
-            /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
-            #[inline]
-            #[must_use]
-            pub const fn union(self, other: Self) -> Self {
-                Self(self.0.union(other.0))
-            }
-
-            /// Returns the difference between the flags in `self` and `other`.
-            ///
-            /// Specifically, the returned set contains all flags present in
-            /// `self`, except for the ones present in `other`.
-            ///
-            /// It is also conceptually equivalent to the "bit-clear" operation:
-            /// `flags & !other` (and this syntax is also supported).
-            ///
-            /// This is equivalent to using the `-` operator (e.g.
-            /// [`ops::Sub`]), as in `flags - other`.
-            ///
-            /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
-            #[inline]
-            #[must_use]
-            pub const fn difference(self, other: Self) -> Self {
-                Self(self.0.difference(other.0))
-            }
-
-            /// Returns the [symmetric difference][sym-diff] between the flags
-            /// in `self` and `other`.
-            ///
-            /// Specifically, the returned set contains the flags present which
-            /// are present in `self` or `other`, but that are not present in
-            /// both. Equivalently, it contains the flags present in *exactly
-            /// one* of the sets `self` and `other`.
-            ///
-            /// This is equivalent to using the `^` operator (e.g.
-            /// [`ops::BitXor`]), as in `flags ^ other`.
-            ///
-            /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
-            /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
-            #[inline]
-            #[must_use]
-            pub const fn symmetric_difference(self, other: Self) -> Self {
-                Self(self.0.symmetric_difference(other.0))
-            }
-
-            /// Returns the complement of this set of flags.
-            ///
-            /// Specifically, the returned set contains all the flags which are
-            /// not set in `self`, but which are allowed for this type.
-            ///
-            /// Alternatively, it can be thought of as the set difference
-            /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`)
-            ///
-            /// This is equivalent to using the `!` operator (e.g.
-            /// [`ops::Not`]), as in `!flags`.
-            ///
-            /// [`Self::all()`]: Self::all
-            /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
-            #[inline]
-            #[must_use]
-            pub const fn complement(self) -> Self {
-                Self(self.0.complement())
-            }
-        }
-
         impl $crate::__private::core::ops::BitOr for $PublicBitFlags {
             type Output = Self;
 
@@ -271,7 +337,7 @@
             /// Adds the set of flags.
             #[inline]
             fn bitor_assign(&mut self, other: Self) {
-                self.0 = self.0.union(other.0);
+                self.0 = self.0 | other.0;
             }
         }
 
@@ -289,7 +355,7 @@
             /// Toggles the set of flags.
             #[inline]
             fn bitxor_assign(&mut self, other: Self) {
-                self.0 = self.0.symmetric_difference(other.0);
+                self.0 = self.0 ^ other.0
             }
         }
 
@@ -307,7 +373,7 @@
             /// Disables all flags disabled in the set.
             #[inline]
             fn bitand_assign(&mut self, other: Self) {
-                self.0 = self.0.intersection(other.0);
+                self.0 = self.0 & other.0;
             }
         }
 
@@ -325,7 +391,7 @@
             /// Disables all flags enabled in the set.
             #[inline]
             fn sub_assign(&mut self, other: Self) {
-                self.0 = self.0.difference(other.0);
+                self.0 = self.0 & !other.0;
             }
         }
 
@@ -356,92 +422,6 @@
                 result
             }
         }
-
-        impl $crate::__private::core::iter::IntoIterator for $PublicBitFlags {
-            type Item = Self;
-            type IntoIter = $Iter;
-
-            fn into_iter(self) -> Self::IntoIter {
-                self.0.iter()
-            }
-        }
-
-        impl $crate::BitFlags for $PublicBitFlags {
-            type Bits = $T;
-
-            type Iter = $Iter;
-            type IterNames = $IterNames;
-
-            fn empty() -> Self {
-                $PublicBitFlags::empty()
-            }
-
-            fn all() -> Self {
-                $PublicBitFlags::all()
-            }
-
-            fn bits(&self) -> $T {
-                $PublicBitFlags::bits(self)
-            }
-
-            fn from_bits(bits: $T) -> $crate::__private::core::option::Option<$PublicBitFlags> {
-                $PublicBitFlags::from_bits(bits)
-            }
-
-            fn from_bits_truncate(bits: $T) -> $PublicBitFlags {
-                $PublicBitFlags::from_bits_truncate(bits)
-            }
-
-            fn from_bits_retain(bits: $T) -> $PublicBitFlags {
-                $PublicBitFlags::from_bits_retain(bits)
-            }
-
-            fn from_name(name: &str) -> $crate::__private::core::option::Option<$PublicBitFlags> {
-                $PublicBitFlags::from_name(name)
-            }
-
-            fn iter(&self) -> Self::Iter {
-                $PublicBitFlags::iter(self)
-            }
-
-            fn iter_names(&self) -> Self::IterNames {
-                $PublicBitFlags::iter_names(self)
-            }
-
-            fn is_empty(&self) -> bool {
-                $PublicBitFlags::is_empty(self)
-            }
-
-            fn is_all(&self) -> bool {
-                $PublicBitFlags::is_all(self)
-            }
-
-            fn intersects(&self, other: $PublicBitFlags) -> bool {
-                $PublicBitFlags::intersects(self, other)
-            }
-
-            fn contains(&self, other: $PublicBitFlags) -> bool {
-                $PublicBitFlags::contains(self, other)
-            }
-
-            fn insert(&mut self, other: $PublicBitFlags) {
-                $PublicBitFlags::insert(self, other)
-            }
-
-            fn remove(&mut self, other: $PublicBitFlags) {
-                $PublicBitFlags::remove(self, other)
-            }
-
-            fn toggle(&mut self, other: $PublicBitFlags) {
-                $PublicBitFlags::toggle(self, other)
-            }
-
-            fn set(&mut self, other: $PublicBitFlags, value: bool) {
-                $PublicBitFlags::set(self, other, value)
-            }
-        }
-
-        impl $crate::__private::ImplementedByBitFlagsMacro for $PublicBitFlags {}
     };
 }
 
@@ -450,7 +430,7 @@
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_consts {
     (
-        $PublicBitFlags:ident {
+        $PublicBitFlags:ident: $T:ty {
             $(
                 $(#[$attr:ident $($args:tt)*])*
                 $Flag:ident = $value:expr;
@@ -460,8 +440,39 @@
         impl $PublicBitFlags {
             $(
                 $(#[$attr $($args)*])*
+                #[allow(
+                    deprecated,
+                    non_upper_case_globals,
+                )]
                 pub const $Flag: Self = Self::from_bits_retain($value);
             )*
         }
+
+        impl $crate::Flags for $PublicBitFlags {
+            const FLAGS: &'static [$crate::Flag<$PublicBitFlags>] = &[
+                $(
+                    __bitflags_expr_safe_attrs!(
+                        $(#[$attr $($args)*])*
+                        {
+                            #[allow(
+                                deprecated,
+                                non_upper_case_globals,
+                            )]
+                            $crate::Flag::new($crate::__private::core::stringify!($Flag), $PublicBitFlags::$Flag)
+                        }
+                    ),
+                )*
+            ];
+
+            type Bits = $T;
+
+            fn bits(&self) -> $T {
+                $PublicBitFlags::bits(self)
+            }
+
+            fn from_bits_retain(bits: $T) -> $PublicBitFlags {
+                $PublicBitFlags::from_bits_retain(bits)
+            }
+        }
     };
 }
diff --git a/src/traits.rs b/src/traits.rs
index 85503e6..f8fc757 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -1,23 +1,50 @@
-use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
+use core::{fmt, ops::{BitAnd, BitOr, BitXor, Not}};
 
-/// A trait that is automatically implemented for all bitflags.
+use crate::{parser::{ParseError, ParseHex, WriteHex}, iter};
+
+/// Metadata for an individual flag.
+pub struct Flag<B> {
+    name: &'static str,
+    value: B,
+}
+
+impl<B> Flag<B> {
+    /// Create a new flag with the given name and value.
+    pub const fn new(name: &'static str, value: B) -> Self {
+        Flag { name, value }
+    }
+
+    /// Get the name of this flag.
+    pub const fn name(&self) -> &'static str {
+        self.name
+    }
+
+    /// Get the value of this flag.
+    pub const fn value(&self) -> &B {
+        &self.value
+    }
+}
+
+/// A set of flags.
 ///
-/// It should not be implemented manually.
-pub trait BitFlags: ImplementedByBitFlagsMacro {
-    /// The underlying integer type.
+/// This trait is automatically implemented for flags types defined using the `bitflags!` macro.
+/// It can also be implemented manually for custom flags types.
+pub trait Flags: Sized + 'static {
+    /// The set of available flags and their names.
+    const FLAGS: &'static [Flag<Self>];
+
+    /// The underlying storage type.
     type Bits: Bits;
 
-    /// An iterator over enabled flags in an instance of the type.
-    type Iter: Iterator<Item = Self>;
-
-    /// An iterator over the raw names and bits for enabled flags in an instance of the type.
-    type IterNames: Iterator<Item = (&'static str, Self)>;
-
     /// Returns an empty set of flags.
-    fn empty() -> Self;
+    fn empty() -> Self {
+        Self::from_bits_retain(Self::Bits::EMPTY)
+    }
 
     /// Returns the set containing all flags.
-    fn all() -> Self;
+    fn all() -> Self {
+        Self::from_bits_truncate(Self::Bits::ALL)
+    }
 
     /// Returns the raw value of the flags currently stored.
     fn bits(&self) -> Self::Bits;
@@ -28,9 +55,15 @@
     /// Note that each [multi-bit flag] is treated as a unit for this comparison.
     ///
     /// [multi-bit flag]: index.html#multi-bit-flags
-    fn from_bits(bits: Self::Bits) -> Option<Self>
-    where
-        Self: Sized;
+    fn from_bits(bits: Self::Bits) -> Option<Self> {
+        let truncated = Self::from_bits_truncate(bits);
+
+        if truncated.bits() == bits {
+            Some(truncated)
+        } else {
+            None
+        }
+    }
 
     /// Convert from underlying bit representation, dropping any bits
     /// that do not correspond to flags.
@@ -38,81 +71,181 @@
     /// Note that each [multi-bit flag] is treated as a unit for this comparison.
     ///
     /// [multi-bit flag]: index.html#multi-bit-flags
-    fn from_bits_truncate(bits: Self::Bits) -> Self;
+    fn from_bits_truncate(bits: Self::Bits) -> Self {
+        if bits == Self::Bits::EMPTY {
+            return Self::empty();
+        }
+
+        let mut truncated = Self::Bits::EMPTY;
+
+        for flag in Self::FLAGS.iter() {
+            let flag = flag.value();
+
+            if bits & flag.bits() == flag.bits() {
+                truncated = truncated | flag.bits();
+            }
+        }
+
+        Self::from_bits_retain(truncated)
+    }
 
     /// Convert from underlying bit representation, preserving all
     /// bits (even those not corresponding to a defined flag).
     fn from_bits_retain(bits: Self::Bits) -> Self;
 
     /// Get the flag for a particular name.
-    fn from_name(name: &str) -> Option<Self>
-    where
-        Self: Sized;
+    fn from_name(name: &str) -> Option<Self> {
+        for flag in Self::FLAGS {
+            if flag.name() == name {
+                return Some(Self::from_bits_retain(flag.value().bits()))
+            }
+        }
+
+        None
+    }
 
     /// Iterate over enabled flag values.
-    fn iter(&self) -> Self::Iter;
+    fn iter(&self) -> iter::Iter<Self> {
+        iter::Iter::new(self)
+    }
 
     /// Iterate over the raw names and bits for enabled flag values.
-    fn iter_names(&self) -> Self::IterNames;
+    fn iter_names(&self) -> iter::IterNames<Self> {
+        iter::IterNames::new(self)
+    }
 
     /// Returns `true` if no flags are currently stored.
-    fn is_empty(&self) -> bool;
+    fn is_empty(&self) -> bool {
+        self.bits() == Self::Bits::EMPTY
+    }
 
     /// Returns `true` if all flags are currently set.
-    fn is_all(&self) -> bool;
+    fn is_all(&self) -> bool {
+        // NOTE: We check against `Self::all` here, not `Self::Bits::ALL`
+        // because the set of all flags may not use all bits
+        Self::all().bits() | self.bits() == self.bits()
+    }
 
     /// Returns `true` if there are flags common to both `self` and `other`.
-    fn intersects(&self, other: Self) -> bool;
+    fn intersects(&self, other: Self) -> bool
+    where
+        Self: Sized,
+    {
+        self.bits() & other.bits() != Self::Bits::EMPTY
+    }
 
     /// Returns `true` if all of the flags in `other` are contained within `self`.
-    fn contains(&self, other: Self) -> bool;
+    fn contains(&self, other: Self) -> bool
+    where
+        Self: Sized,
+    {
+        self.bits() & other.bits() == other.bits()
+    }
 
     /// Inserts the specified flags in-place.
-    fn insert(&mut self, other: Self);
+    fn insert(&mut self, other: Self)
+    where
+        Self: Sized,
+    {
+        *self = Self::from_bits_retain(self.bits() | other.bits());
+    }
 
     /// Removes the specified flags in-place.
-    fn remove(&mut self, other: Self);
+    fn remove(&mut self, other: Self)
+    where
+        Self: Sized,
+    {
+        *self = Self::from_bits_retain(self.bits() & !other.bits());
+    }
 
     /// Toggles the specified flags in-place.
-    fn toggle(&mut self, other: Self);
+    fn toggle(&mut self, other: Self)
+    where
+        Self: Sized,
+    {
+        *self = Self::from_bits_retain(self.bits() ^ other.bits());
+    }
 
     /// Inserts or removes the specified flags depending on the passed value.
-    fn set(&mut self, other: Self, value: bool);
+    fn set(&mut self, other: Self, value: bool)
+    where
+        Self: Sized,
+    {
+        if value {
+            self.insert(other);
+        } else {
+            self.remove(other);
+        }
+    }
+
+    /// Returns the intersection between the flags in `self` and
+    /// `other`.
+    ///
+    /// Specifically, the returned set contains only the flags which are
+    /// present in *both* `self` *and* `other`.
+    #[must_use]
+    fn intersection(self, other: Self) -> Self {
+        Self::from_bits_retain(self.bits() & other.bits())
+    }
+
+    /// Returns the union of between the flags in `self` and `other`.
+    ///
+    /// Specifically, the returned set contains all flags which are
+    /// present in *either* `self` *or* `other`, including any which are
+    /// present in both (see [`Self::symmetric_difference`] if that
+    /// is undesirable).
+    #[must_use]
+    fn union(self, other: Self) -> Self {
+        Self::from_bits_retain(self.bits() | other.bits())
+    }
+
+    /// Returns the difference between the flags in `self` and `other`.
+    ///
+    /// Specifically, the returned set contains all flags present in
+    /// `self`, except for the ones present in `other`.
+    ///
+    /// It is also conceptually equivalent to the "bit-clear" operation:
+    /// `flags & !other` (and this syntax is also supported).
+    #[must_use]
+    fn difference(self, other: Self) -> Self {
+        Self::from_bits_retain(self.bits() & !other.bits())
+    }
+
+    /// Returns the [symmetric difference][sym-diff] between the flags
+    /// in `self` and `other`.
+    ///
+    /// Specifically, the returned set contains the flags present which
+    /// are present in `self` or `other`, but that are not present in
+    /// both. Equivalently, it contains the flags present in *exactly
+    /// one* of the sets `self` and `other`.
+    ///
+    /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
+    #[must_use]
+    fn symmetric_difference(self, other: Self) -> Self {
+        Self::from_bits_retain(self.bits() ^ other.bits())
+    }
+
+    /// Returns the complement of this set of flags.
+    ///
+    /// Specifically, the returned set contains all the flags which are
+    /// not set in `self`, but which are allowed for this type.
+    #[must_use]
+    fn complement(self) -> Self {
+        Self::from_bits_truncate(!self.bits())
+    }
 }
 
-/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro.
-///
-/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their
-/// manual implementations won't break between non-breaking releases.
-#[doc(hidden)]
-pub trait ImplementedByBitFlagsMacro {}
-
-// Not re-exported
-pub trait Sealed {}
-
-// Private implementation details
-//
-// The `Bits`, `PublicFlags`, and `InternalFlags` traits are implementation details of the `bitflags!`
-// macro that we're free to change here. They work with the `bitflags!` macro to separate the generated
-// code that belongs to end-users, and the generated code that belongs to this library.
-
-/// A private trait that encodes the requirements of underlying bits types that can hold flags.
-///
-/// This trait may be made public at some future point, but it presents a compatibility hazard
-/// so is left internal for now.
-#[doc(hidden)]
+/// Underlying storage for a flags type.
 pub trait Bits:
     Clone
     + Copy
-    + BitAnd
-    + BitAndAssign
-    + BitOr
-    + BitOrAssign
-    + BitXor
-    + BitXorAssign
-    + Not
+    + PartialEq
+    + BitAnd<Output = Self>
+    + BitOr<Output = Self>
+    + BitXor<Output = Self>
+    + Not<Output = Self>
     + Sized
-    + Sealed
+    + 'static
 {
     /// The value of `Self` where no bits are set.
     const EMPTY: Self;
@@ -121,6 +254,10 @@
     const ALL: Self;
 }
 
+// Not re-exported: prevent custom `Bits` impls being used in the `bitflags!` macro,
+// or they may fail to compile based on crate features
+pub trait Primitive {}
+
 macro_rules! impl_bits {
     ($($u:ty, $i:ty,)*) => {
         $(
@@ -134,8 +271,32 @@
                 const ALL: $i = <$u>::MAX as $i;
             }
 
-            impl Sealed for $u {}
-            impl Sealed for $i {}
+            impl ParseHex for $u {
+                fn parse_hex(input: &str) -> Result<Self, ParseError> {
+                    <$u>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
+                }
+            }
+
+            impl ParseHex for $i {
+                fn parse_hex(input: &str) -> Result<Self, ParseError> {
+                    <$i>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
+                }
+            }
+
+            impl WriteHex for $u {
+                fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
+                    write!(writer, "{:x}", self)
+                }
+            }
+
+            impl WriteHex for $i {
+                fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
+                    write!(writer, "{:x}", self)
+                }
+            }
+
+            impl Primitive for $i {}
+            impl Primitive for $u {}
         )*
     }
 }
@@ -152,6 +313,37 @@
 /// A trait for referencing the `bitflags`-owned internal type
 /// without exposing it publicly.
 pub trait PublicFlags {
+    /// The type of the underlying storage.
+    type Primitive: Primitive;
+
     /// The type of the internal field on the generated flags type.
     type Internal;
 }
+
+#[deprecated(note = "use the `Flags` trait instead")]
+pub trait BitFlags: ImplementedByBitFlagsMacro + Flags {
+    /// An iterator over enabled flags in an instance of the type.
+    type Iter: Iterator<Item = Self>;
+
+    /// An iterator over the raw names and bits for enabled flags in an instance of the type.
+    type IterNames: Iterator<Item = (&'static str, Self)>;
+}
+
+#[allow(deprecated)]
+impl<B: Flags> BitFlags for B {
+    type Iter = iter::Iter<Self>;
+    type IterNames = iter::IterNames<Self>;
+}
+
+impl<B: Flags> ImplementedByBitFlagsMacro for B {}
+
+/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro.
+///
+/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their
+/// manual implementations won't break between non-breaking releases.
+#[doc(hidden)]
+pub trait ImplementedByBitFlagsMacro {}
+
+pub(crate) mod __private {
+    pub use super::{ImplementedByBitFlagsMacro, PublicFlags};
+}
diff --git a/tests/basic.rs b/tests/basic.rs
deleted file mode 100644
index 73a52be..0000000
--- a/tests/basic.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![no_std]
-
-use bitflags::bitflags;
-
-bitflags! {
-    /// baz
-    struct Flags: u32 {
-        const A = 0b00000001;
-        #[doc = "bar"]
-        const B = 0b00000010;
-        const C = 0b00000100;
-        #[doc = "foo"]
-        const ABC = Flags::A.bits | Flags::B.bits | Flags::C.bits;
-    }
-}
-
-#[test]
-fn basic() {
-    assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C);
-}
diff --git a/tests/compile-fail/.gitignore b/tests/compile-fail/.gitignore
deleted file mode 100644
index 4dd9abc..0000000
--- a/tests/compile-fail/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.stderr
diff --git a/tests/compile-fail/impls/copy.rs b/tests/compile-fail/impls/copy.rs
deleted file mode 100644
index 38f4822..0000000
--- a/tests/compile-fail/impls/copy.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    #[derive(Clone, Copy)]
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-fail/impls/copy.stderr.beta b/tests/compile-fail/impls/copy.stderr.beta
deleted file mode 100644
index 0c13aa5..0000000
--- a/tests/compile-fail/impls/copy.stderr.beta
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Flags`
- --> $DIR/copy.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(Clone, Copy)]
-  | |              ----- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `Flags`
- --> $DIR/copy.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(Clone, Copy)]
-  | |                     ---- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile-fail/impls/eq.rs b/tests/compile-fail/impls/eq.rs
deleted file mode 100644
index 4abbd63..0000000
--- a/tests/compile-fail/impls/eq.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    #[derive(PartialEq, Eq)]
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-fail/impls/eq.stderr.beta b/tests/compile-fail/impls/eq.stderr.beta
deleted file mode 100644
index 8a1a3b4..0000000
--- a/tests/compile-fail/impls/eq.stderr.beta
+++ /dev/null
@@ -1,55 +0,0 @@
-error[E0119]: conflicting implementations of trait `std::cmp::PartialEq` for type `Flags`
- --> $DIR/eq.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(PartialEq, Eq)]
-  | |              --------- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0119]: conflicting implementations of trait `std::cmp::Eq` for type `Flags`
- --> $DIR/eq.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(PartialEq, Eq)]
-  | |                         -- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0119]: conflicting implementations of trait `std::marker::StructuralPartialEq` for type `Flags`
- --> $DIR/eq.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(PartialEq, Eq)]
-  | |              --------- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0119]: conflicting implementations of trait `std::marker::StructuralEq` for type `Flags`
- --> $DIR/eq.rs:3:1
-  |
-3 | / bitflags! {
-4 | |     #[derive(PartialEq, Eq)]
-  | |                         -- first implementation here
-5 | |     struct Flags: u32 {
-6 | |         const A = 0b00000001;
-7 | |     }
-8 | | }
-  | |_^ conflicting implementation for `Flags`
-  |
-  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile-fail/non_integer_base/all_defined.rs b/tests/compile-fail/non_integer_base/all_defined.rs
deleted file mode 100644
index c2856b1..0000000
--- a/tests/compile-fail/non_integer_base/all_defined.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-use std::{
-    fmt::{
-        self,
-        Debug,
-        Display,
-        LowerHex,
-        UpperHex,
-        Octal,
-        Binary,
-    },
-    ops::{
-        BitAnd,
-        BitOr,
-        BitXor,
-        BitAndAssign,
-        BitOrAssign,
-        BitXorAssign,
-        Not,
-    },
-};
-
-use bitflags::bitflags;
-
-// Ideally we'd actually want this to work, but currently need something like `num`'s `Zero`
-// With some design work it could be made possible
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-struct MyInt(u8);
-
-impl BitAnd for MyInt {
-    type Output = Self;
-
-    fn bitand(self, other: Self) -> Self {
-        MyInt(self.0 & other.0)
-    }
-}
-
-impl BitOr for MyInt {
-    type Output = Self;
-
-    fn bitor(self, other: Self) -> Self {
-        MyInt(self.0 | other.0)
-    }
-}
-
-impl BitXor for MyInt {
-    type Output = Self;
-
-    fn bitxor(self, other: Self) -> Self {
-        MyInt(self.0 ^ other.0)
-    }
-}
-
-impl BitAndAssign for MyInt {
-    fn bitand_assign(&mut self, other: Self) {
-        self.0 &= other.0
-    }
-}
-
-impl BitOrAssign for MyInt {
-    fn bitor_assign(&mut self, other: Self) {
-        self.0 |= other.0
-    }
-}
-
-impl BitXorAssign for MyInt {
-    fn bitxor_assign(&mut self, other: Self) {
-        self.0 ^= other.0
-    }
-}
-
-impl Debug for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Debug::fmt(&self.0, f)
-    }
-}
-
-impl Display for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(&self.0, f)
-    }
-}
-
-impl LowerHex for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        LowerHex::fmt(&self.0, f)
-    }
-}
-
-impl UpperHex for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        UpperHex::fmt(&self.0, f)
-    }
-}
-
-impl Octal for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Octal::fmt(&self.0, f)
-    }
-}
-
-impl Binary for MyInt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Binary::fmt(&self.0, f)
-    }
-}
-
-impl Not for MyInt {
-    type Output = MyInt;
-
-    fn not(self) -> Self {
-        MyInt(!self.0)
-    }
-}
-
-bitflags! {
-    struct Flags128: MyInt {
-        const A = MyInt(0b0000_0001u8);
-        const B = MyInt(0b0000_0010u8);
-        const C = MyInt(0b0000_0100u8);
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-fail/non_integer_base/all_defined.stderr.beta b/tests/compile-fail/non_integer_base/all_defined.stderr.beta
deleted file mode 100644
index 1f0fb5c..0000000
--- a/tests/compile-fail/non_integer_base/all_defined.stderr.beta
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0308]: mismatched types
-   --> $DIR/all_defined.rs:115:1
-    |
-115 | / bitflags! {
-116 | |     struct Flags128: MyInt {
-117 | |         const A = MyInt(0b0000_0001u8);
-118 | |         const B = MyInt(0b0000_0010u8);
-119 | |         const C = MyInt(0b0000_0100u8);
-120 | |     }
-121 | | }
-    | |_^ expected struct `MyInt`, found integer
-    |
-    = note: this error originates in the macro `__impl_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0308]: mismatched types
-   --> $DIR/all_defined.rs:115:1
-    |
-115 | / bitflags! {
-116 | |     struct Flags128: MyInt {
-117 | |         const A = MyInt(0b0000_0001u8);
-118 | |         const B = MyInt(0b0000_0010u8);
-119 | |         const C = MyInt(0b0000_0100u8);
-120 | |     }
-121 | | }
-    | |_^ expected struct `MyInt`, found integer
-    |
-    = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile-fail/non_integer_base/all_missing.rs b/tests/compile-fail/non_integer_base/all_missing.rs
deleted file mode 100644
index fff6b2c..0000000
--- a/tests/compile-fail/non_integer_base/all_missing.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use bitflags::bitflags;
-
-struct MyInt(u8);
-
-bitflags! {
-    struct Flags128: MyInt {
-        const A = MyInt(0b0000_0001);
-        const B = MyInt(0b0000_0010);
-        const C = MyInt(0b0000_0100);
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-fail/non_integer_base/all_missing.stderr.beta b/tests/compile-fail/non_integer_base/all_missing.stderr.beta
deleted file mode 100644
index ee95f83..0000000
--- a/tests/compile-fail/non_integer_base/all_missing.stderr.beta
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0204]: the trait `Copy` may not be implemented for this type
-  --> $DIR/all_missing.rs:5:1
-   |
-5  | / bitflags! {
-6  | |     struct Flags128: MyInt {
-7  | |         const A = MyInt(0b0000_0001);
-8  | |         const B = MyInt(0b0000_0010);
-9  | |         const C = MyInt(0b0000_0100);
-10 | |     }
-11 | | }
-   | |_^ this field does not implement `Copy`
-   |
-   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile-fail/visibility/private_field.rs b/tests/compile-fail/visibility/private_field.rs
deleted file mode 100644
index a6a3912..0000000
--- a/tests/compile-fail/visibility/private_field.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-mod example {
-    use bitflags::bitflags;
-
-    bitflags! {
-        pub struct Flags1: u32 {
-            const FLAG_A = 0b00000001;
-        }
-    }
-}
-
-fn main() {
-    let flag1 = example::Flags1::FLAG_A.bits;
-}
diff --git a/tests/compile-fail/visibility/private_field.stderr.beta b/tests/compile-fail/visibility/private_field.stderr.beta
deleted file mode 100644
index 58a0466..0000000
--- a/tests/compile-fail/visibility/private_field.stderr.beta
+++ /dev/null
@@ -1,10 +0,0 @@
-error[E0616]: field `bits` of struct `Flags1` is private
-  --> $DIR/private_field.rs:12:41
-   |
-12 |     let flag1 = example::Flags1::FLAG_A.bits;
-   |                                         ^^^^ private field
-   |
-help: a method `bits` also exists, call it with parentheses
-   |
-12 |     let flag1 = example::Flags1::FLAG_A.bits();
-   |                                             ^^
diff --git a/tests/compile-fail/visibility/private_flags.rs b/tests/compile-fail/visibility/private_flags.rs
deleted file mode 100644
index 85a5b18..0000000
--- a/tests/compile-fail/visibility/private_flags.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-mod example {
-    use bitflags::bitflags;
-
-    bitflags! {
-        pub struct Flags1: u32 {
-            const FLAG_A = 0b00000001;
-        }
-
-        struct Flags2: u32 {
-            const FLAG_B = 0b00000010;
-        }
-    }
-}
-
-fn main() {
-    let flag1 = example::Flags1::FLAG_A;
-    let flag2 = example::Flags2::FLAG_B;
-}
diff --git a/tests/compile-fail/visibility/private_flags.stderr.beta b/tests/compile-fail/visibility/private_flags.stderr.beta
deleted file mode 100644
index d23f832..0000000
--- a/tests/compile-fail/visibility/private_flags.stderr.beta
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0603]: struct `Flags2` is private
-  --> $DIR/private_flags.rs:17:26
-   |
-17 |     let flag2 = example::Flags2::FLAG_B;
-   |                          ^^^^^^ private struct
-   |
-note: the struct `Flags2` is defined here
-  --> $DIR/private_flags.rs:4:5
-   |
-4  | /     bitflags! {
-5  | |         pub struct Flags1: u32 {
-6  | |             const FLAG_A = 0b00000001;
-7  | |         }
-...  |
-11 | |         }
-12 | |     }
-   | |_____^
-   = note: this error originates in the macro `bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile-fail/visibility/pub_const.rs b/tests/compile-fail/visibility/pub_const.rs
deleted file mode 100644
index b90f0ce..0000000
--- a/tests/compile-fail/visibility/pub_const.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    pub struct Flags1: u32 {
-        pub const FLAG_A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-fail/visibility/pub_const.stderr.beta b/tests/compile-fail/visibility/pub_const.stderr.beta
deleted file mode 100644
index b01122c..0000000
--- a/tests/compile-fail/visibility/pub_const.stderr.beta
+++ /dev/null
@@ -1,5 +0,0 @@
-error: no rules expected the token `pub`
- --> $DIR/pub_const.rs:5:9
-  |
-5 |         pub const FLAG_A = 0b00000001;
-  |         ^^^ no rules expected this token in macro call
diff --git a/tests/compile-pass/impls/convert.rs b/tests/compile-pass/impls/convert.rs
deleted file mode 100644
index 1f02982..0000000
--- a/tests/compile-pass/impls/convert.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-impl From<u32> for Flags {
-    fn from(v: u32) -> Flags {
-        Flags::from_bits_truncate(v)
-    }
-}
-
-fn main() {
-
-}
diff --git a/tests/compile-pass/impls/default.rs b/tests/compile-pass/impls/default.rs
deleted file mode 100644
index a97b653..0000000
--- a/tests/compile-pass/impls/default.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    #[derive(Default)]
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-pass/impls/inherent_methods.rs b/tests/compile-pass/impls/inherent_methods.rs
deleted file mode 100644
index 3052c46..0000000
--- a/tests/compile-pass/impls/inherent_methods.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-impl Flags {
-    pub fn new() -> Flags {
-        Flags::A
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-pass/redefinition/core.rs b/tests/compile-pass/redefinition/core.rs
deleted file mode 100644
index 4754921..0000000
--- a/tests/compile-pass/redefinition/core.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use bitflags::bitflags;
-
-// Checks for possible errors caused by overriding names used by `bitflags!` internally.
-
-mod core {}
-mod _core {}
-
-bitflags! {
-    struct Test: u8 {
-        const A = 1;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-pass/redefinition/stringify.rs b/tests/compile-pass/redefinition/stringify.rs
deleted file mode 100644
index b04f2f6..0000000
--- a/tests/compile-pass/redefinition/stringify.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use bitflags::bitflags;
-
-// Checks for possible errors caused by overriding names used by `bitflags!` internally.
-
-#[allow(unused_macros)]
-macro_rules! stringify {
-    ($($t:tt)*) => { "..." };
-}
-
-bitflags! {
-    struct Test: u8 {
-        const A = 1;
-    }
-}
-
-fn main() {
-    // Just make sure we don't call the redefined `stringify` macro
-    assert_eq!(format!("{:?}", Test::A), "A");
-}
diff --git a/tests/compile-pass/repr/c.rs b/tests/compile-pass/repr/c.rs
deleted file mode 100644
index 6feba36..0000000
--- a/tests/compile-pass/repr/c.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    #[repr(C)]
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-pass/repr/transparent.rs b/tests/compile-pass/repr/transparent.rs
deleted file mode 100644
index e38db4d..0000000
--- a/tests/compile-pass/repr/transparent.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    #[repr(transparent)]
-    struct Flags: u32 {
-        const A = 0b00000001;
-    }
-}
-
-fn main() {}
diff --git a/tests/compile-pass/visibility/bits_field.rs b/tests/compile-pass/visibility/bits_field.rs
deleted file mode 100644
index 33a7967..0000000
--- a/tests/compile-pass/visibility/bits_field.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use bitflags::bitflags;
-
-bitflags! {
-    pub struct Flags1: u32 {
-        const FLAG_A = 0b00000001;
-    }
-}
-
-fn main() {
-    assert_eq!(0b00000001, Flags1::FLAG_A.bits);
-}
diff --git a/tests/compile-pass/visibility/pub_in.rs b/tests/compile-pass/visibility/pub_in.rs
deleted file mode 100644
index c11050e..0000000
--- a/tests/compile-pass/visibility/pub_in.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-mod a {
-    mod b {
-        use bitflags::bitflags;
-
-        bitflags! {
-            pub(in crate::a) struct Flags: u32 {
-                const FLAG_A = 0b00000001;
-            }
-        }
-    }
-
-    pub fn flags() -> u32 {
-        b::Flags::FLAG_A.bits()
-    }
-}
-
-fn main() {
-    assert_eq!(0b00000001, a::flags());
-}
diff --git a/tests/compile.rs b/tests/compile.rs
deleted file mode 100644
index ed02d01..0000000
--- a/tests/compile.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use std::{
-    fs,
-    ffi::OsStr,
-    io,
-    path::Path,
-};
-
-use walkdir::WalkDir;
-
-#[test]
-fn fail() {
-    prepare_stderr_files("tests/compile-fail").unwrap();
-
-    let t = trybuild::TestCases::new();
-    t.compile_fail("tests/compile-fail/**/*.rs");
-}
-
-#[test]
-fn pass() {
-    let t = trybuild::TestCases::new();
-    t.pass("tests/compile-pass/**/*.rs");
-}
-
-// Compiler messages may change between versions
-// We don't want to have to track these too closely for `bitflags`, but
-// having some message to check makes sure user-facing errors are sensical.
-// 
-// The approach we use is to run the test on all compilers, but only check stderr
-// output on beta (which is the next stable release). We do this by default ignoring
-// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files
-// when we happen to be running on a beta compiler.
-fn prepare_stderr_files(path: impl AsRef<Path>) -> io::Result<()> {
-    for entry in WalkDir::new(path) {
-        let entry = entry?;
-
-        if entry.path().extension().and_then(OsStr::to_str) == Some("beta") {
-            let renamed = entry.path().with_extension("");
-
-            // Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta`
-            // file if it exists. On `beta` compilers, we'll recreate it. On other compilers,
-            // we don't want to end up checking it anyways.
-            if renamed.exists() {
-                fs::remove_file(&renamed)?;
-            }
-
-            rename_beta_stderr(entry.path(), renamed)?;
-        }
-    }
-
-    Ok(())
-}
-
-#[rustversion::beta]
-fn rename_beta_stderr(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
-    fs::copy(from, to)?;
-
-    Ok(())
-}
-
-#[rustversion::not(beta)]
-fn rename_beta_stderr(_: impl AsRef<Path>, _: impl AsRef<Path>) -> io::Result<()> {
-    Ok(())
-}