Upgrade bitflags to 2.4.2 am: 5fc2b79734

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

Change-Id: I5acd2ea9b76850e44f5659a6097133a75a7c1f7a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 6877a2f..49de48e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "09f71f492d0f76d63cd286c3869c70676297e204"
+    "sha1": "a5f9ce20e9d18444aa9b20c8fea9c00155cbafa3"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index d6d6e28..7144038 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.3.2",
+    cargo_pkg_version: "2.4.2",
     srcs: ["src/lib.rs"],
     edition: "2021",
     apex_available: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5512ceb..fd435d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,66 @@
+# 2.4.2
+
+## What's Changed
+* Cargo.toml: Anchor excludes to root of the package by @jamessan in https://github.com/bitflags/bitflags/pull/387
+* Update error messages by @KodrAus in https://github.com/bitflags/bitflags/pull/390
+* Add support for impl mode structs to be repr(packed) by @GnomedDev in https://github.com/bitflags/bitflags/pull/388
+* Remove old `unused_tuple_struct_fields` lint by @dtolnay in https://github.com/bitflags/bitflags/pull/393
+* Delete use of `local_inner_macros` by @dtolnay in https://github.com/bitflags/bitflags/pull/392
+
+## New Contributors
+* @jamessan made their first contribution in https://github.com/bitflags/bitflags/pull/387
+* @GnomedDev made their first contribution in https://github.com/bitflags/bitflags/pull/388
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.4.1...2.4.2
+
+# 2.4.1
+
+## What's Changed
+* Allow some new pedantic clippy lints by @KodrAus in https://github.com/bitflags/bitflags/pull/380
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.4.0...2.4.1
+
+# 2.4.0
+
+## What's Changed
+* Remove html_root_url by @eldruin in https://github.com/bitflags/bitflags/pull/368
+* Support unnamed flags by @KodrAus in https://github.com/bitflags/bitflags/pull/371
+* Update smoke test to verify all Clippy and rustc lints by @MitMaro in https://github.com/bitflags/bitflags/pull/374
+* Specify the behavior of bitflags by @KodrAus in https://github.com/bitflags/bitflags/pull/369
+
+## New Contributors
+* @eldruin made their first contribution in https://github.com/bitflags/bitflags/pull/368
+* @MitMaro made their first contribution in https://github.com/bitflags/bitflags/pull/374
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.3.3...2.4.0
+
+# 2.3.3
+
+## Changes to `-=`
+
+The `-=` operator was incorrectly changed to truncate bits that didn't correspond to valid flags in `2.3.0`. This has
+been fixed up so it once again behaves the same as `-` and `difference`.
+
+## Changes to `!`
+
+The `!` operator previously called `Self::from_bits_truncate`, which would truncate any bits that only partially
+overlapped with a valid flag. It will now use `bits & Self::all().bits()`, so any bits that overlap any bits
+specified by any flag will be respected. This is unlikely to have any practical implications, but enables defining
+a flag like `const ALL = !0` as a way to signal that any bit pattern is a known set of flags.
+
+## Changes to formatting
+
+Zero-valued flags will never be printed. You'll either get `0x0` for empty flags using debug formatting, or the
+set of flags with zero-valued flags omitted for others.
+
+Composite flags will no longer be redundantly printed if there are extra bits to print at the end that don't correspond
+to a valid flag.
+
+## What's Changed
+* Fix up incorrect sub assign behavior and other cleanups by @KodrAus in https://github.com/bitflags/bitflags/pull/366
+
+**Full Changelog**: https://github.com/bitflags/bitflags/compare/2.3.2...2.3.3
+
 # 2.3.2
 
 ## What's Changed
diff --git a/Cargo.toml b/Cargo.toml
index 7b9cfb0..43595a5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,11 +13,11 @@
 edition = "2021"
 rust-version = "1.56.0"
 name = "bitflags"
-version = "2.3.2"
+version = "2.4.2"
 authors = ["The Rust Project Developers"]
 exclude = [
-    "tests",
-    ".github",
+    "/tests",
+    "/.github",
 ]
 description = """
 A macro to generate structures which behave like bitflags.
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 7d57882..764bfdc 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,9 +1,7 @@
 [package]
 name = "bitflags"
-# NB: When modifying, also modify:
-#   1. html_root_url in lib.rs
-#   2. number in readme (for breaking changes)
-version = "2.3.2"
+# NB: When modifying, also modify the number in readme (for breaking changes)
+version = "2.4.2"
 edition = "2021"
 rust-version = "1.56.0"
 authors = ["The Rust Project Developers"]
@@ -17,7 +15,7 @@
 description = """
 A macro to generate structures which behave like bitflags.
 """
-exclude = ["tests", ".github"]
+exclude = ["/tests", "/.github"]
 
 [dependencies]
 serde = { version = "1.0", optional = true, default-features = false }
diff --git a/METADATA b/METADATA
index 0872db8..2863dcb 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update rust/crates/bitflags
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/rust/crates/bitflags
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "bitflags"
 description: "A macro to generate structures which behave like bitflags."
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://crates.io/crates/bitflags"
-  }
-  url {
-    type: ARCHIVE
-    value: "https://static.crates.io/crates/bitflags/bitflags-2.3.2.crate"
-  }
-  version: "2.3.2"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 6
-    day: 13
+    year: 2024
+    month: 2
+    day: 21
+  }
+  homepage: "https://crates.io/crates/bitflags"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/bitflags/bitflags-2.4.2.crate"
+    version: "2.4.2"
   }
 }
diff --git a/README.md b/README.md
index fada7a6..a560bc8 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,20 @@
 [![Documentation](https://docs.rs/bitflags/badge.svg)](https://docs.rs/bitflags)
 ![License](https://img.shields.io/crates/l/bitflags.svg)
 
-A Rust macro to generate structures which behave like a set of bitflags
+`bitflags` generates flags enums with well-defined semantics and ergonomic end-user APIs.
+
+You can use `bitflags` to:
+
+- provide more user-friendly bindings to C APIs where flags may or may not be fully known in advance.
+- generate efficient options types with string parsing and formatting support.
+
+You can't use `bitflags` to:
+
+- guarantee only bits corresponding to defined flags will ever be set. `bitflags` allows access to the underlying bits type so arbitrary bits may be set.
+- define bitfields. `bitflags` only generates types where set bits denote the presence of some combination of flags.
 
 - [Documentation](https://docs.rs/bitflags)
+- [Specification](https://github.com/bitflags/bitflags/blob/main/spec.md)
 - [Release notes](https://github.com/bitflags/bitflags/releases)
 
 ## Usage
@@ -17,7 +28,7 @@
 
 ```toml
 [dependencies]
-bitflags = "2.3.2"
+bitflags = "2.4.2"
 ```
 
 and this to your source code:
@@ -35,11 +46,17 @@
 
 // The `bitflags!` macro generates `struct`s that manage a set of flags.
 bitflags! {
+    /// Represents a set of flags.
     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     struct Flags: u32 {
+        /// The value `A`, at bit position `0`.
         const A = 0b00000001;
+        /// The value `B`, at bit position `1`.
         const B = 0b00000010;
+        /// The value `C`, at bit position `2`.
         const C = 0b00000100;
+
+        /// The combination of `A`, `B`, and `C`.
         const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
     }
 }
diff --git a/examples/custom_bits_type.rs b/examples/custom_bits_type.rs
index 0364a2b..8924bfd 100644
--- a/examples/custom_bits_type.rs
+++ b/examples/custom_bits_type.rs
@@ -1,6 +1,6 @@
 use std::ops::{BitAnd, BitOr, BitXor, Not};
 
-use bitflags::{Flags, Flag, Bits};
+use bitflags::{Bits, Flag, Flags};
 
 // Define a custom container that can be used in flags types
 // Note custom bits types can't be used in `bitflags!`
@@ -25,7 +25,11 @@
     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]])
+        CustomBits([
+            self.0[0] & other.0[0],
+            self.0[1] & other.0[1],
+            self.0[2] & other.0[2],
+        ])
     }
 }
 
@@ -33,7 +37,11 @@
     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]])
+        CustomBits([
+            self.0[0] | other.0[0],
+            self.0[1] | other.0[1],
+            self.0[2] | other.0[2],
+        ])
     }
 }
 
@@ -41,7 +49,11 @@
     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]])
+        CustomBits([
+            self.0[0] & other.0[0],
+            self.0[1] & other.0[1],
+            self.0[2] & other.0[2],
+        ])
     }
 }
 
diff --git a/examples/macro_free.rs b/examples/macro_free.rs
index ec3a8cb..7563379 100644
--- a/examples/macro_free.rs
+++ b/examples/macro_free.rs
@@ -4,7 +4,7 @@
 
 use std::{fmt, str};
 
-use bitflags::{Flags, Flag};
+use bitflags::{Flag, Flags};
 
 // First: Define your flags type. It just needs to be `Sized + 'static`.
 pub struct ManualFlags(u32);
@@ -54,5 +54,8 @@
 }
 
 fn main() {
-    println!("{}", ManualFlags::A.union(ManualFlags::B).union(ManualFlags::C));
+    println!(
+        "{}",
+        ManualFlags::A.union(ManualFlags::B).union(ManualFlags::C)
+    );
 }
diff --git a/spec.md b/spec.md
new file mode 100644
index 0000000..43dae1d
--- /dev/null
+++ b/spec.md
@@ -0,0 +1,552 @@
+# Bitflags
+
+`bitflags` generates flags enums with well-defined semantics and ergonomic end-user APIs.
+
+You can use `bitflags` to:
+
+- provide more user-friendly bindings to C APIs where flags may or may not be fully known in advance.
+- generate efficient options types with string parsing and formatting support.
+
+You can't use `bitflags` to:
+
+- guarantee only bits corresponding to defined flags will ever be set. `bitflags` allows access to the underlying bits type so arbitrary bits may be set.
+- define bitfields. `bitflags` only generates types where set bits denote the presence of some combination of flags.
+
+## Definitions
+
+This section formally defines the terminology and semantics of `bitflags`. It's organized so more fundamental concepts are introduced before those that build on them. It may be helpful to start from the bottom of the section and refer back up to concepts defined earlier.
+
+Examples use `bitflags` syntax with `u8` as the bits type.
+
+### Bits type
+
+A type that defines a fixed number of bits at specific locations.
+
+----
+
+Bits types are typically fixed-width unsigned integers. For example, `u8` is a bits type that defines 8 bits; bit-0 through bit-7.
+
+### Bits value
+
+An instance of a bits type where each bit may be set (`1`) or unset (`0`).
+
+----
+
+Some examples of bits values for the bits type `u8` are:
+
+```rust
+0b0000_0000
+0b1111_1111
+0b1010_0101
+```
+
+#### Equality
+
+Two bits values are equal if their bits are in the same configuration; set bits in one are set in the other, and unset bits in one are unset in the other.
+
+#### Operations
+
+Bits values define the bitwise operators and (`&`), or (`|`), exclusive-or (`^`), and negation (`!`) that apply to each of their bits.
+
+### Flag
+
+A set of bits in a bits type that may have a unique name.
+
+----
+
+Bits are not required to be exclusive to a flag. Bits are not required to be contiguous.
+
+The following is a flag for `u8` with the name `A` that includes bit-0:
+
+```rust
+const A = 0b0000_0001;
+```
+
+The following is a flag for `u8` with the name `B` that includes bit-0, and bit-5:
+
+```rust
+const B = 0b0010_0001;
+```
+
+#### Named flag
+
+A flag with a name.
+
+----
+
+The following is a named flag, where the name is `A`:
+
+```rust
+const A = 0b0000_0001;
+```
+
+#### Unnamed flag
+
+A flag without a name.
+
+----
+
+The following is an unnamed flag:
+
+```rust
+const _ = 0b0000_0001;
+```
+
+#### Zero-bit flag
+
+A flag with a set of zero bits.
+
+----
+
+The following is a zero-bit flag:
+
+```rust
+const ZERO = 0b0000_0000;
+```
+
+#### Single-bit flag
+
+A flag with a set of one bit.
+
+----
+
+The following are single-bit flags:
+
+```rust
+const A = 0b0000_0001;
+const B = 0b0000_0010;
+```
+
+#### Multi-bit flag
+
+A flag with a set of more than one bit.
+
+----
+
+The following are multi-bit flags:
+
+```rust
+const A = 0b0000_0011;
+const B = 0b1111_1111;
+```
+
+### Flags type
+
+A set of defined flags over a specific bits type.
+
+#### Known bit
+
+A bit in any defined flag.
+
+----
+
+In the following flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0001;
+    const B = 0b0000_0010;
+    const C = 0b0000_0100;
+}
+```
+
+the known bits are:
+
+```rust
+0b0000_0111
+```
+
+#### Unknown bit
+
+A bit not in any defined flag.
+
+----
+
+In the following flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0001;
+    const B = 0b0000_0010;
+    const C = 0b0000_0100;
+}
+```
+
+the unknown bits are:
+
+```rust
+0b1111_1000
+```
+
+### Flags value
+
+An instance of a flags type using its specific bits value for storage.
+
+The flags value of a flag is one where each of its bits is set, and all others are unset.
+
+#### Contains
+
+Whether all set bits in a source flags value are also set in a target flags value.
+
+----
+
+Given the flags value:
+
+```rust
+0b0000_0011
+```
+
+the following flags values are contained:
+
+```rust
+0b0000_0000
+0b0000_0010
+0b0000_0001
+0b0000_0011
+```
+
+but the following flags values are not contained:
+
+```rust
+0b0000_1000
+0b0000_0110
+```
+
+#### Intersects
+
+Whether any set bits in a source flags value are also set in a target flags value.
+
+----
+
+Given the flags value:
+
+```rust
+0b0000_0011
+```
+
+the following flags intersect:
+
+```rust
+0b0000_0010
+0b0000_0001
+0b1111_1111
+```
+
+but the following flags values do not intersect:
+
+```rust
+0b0000_0000
+0b1111_0000
+```
+
+#### Empty
+
+Whether all bits in a flags value are unset.
+
+----
+
+The following flags value is empty:
+
+```rust
+0b0000_0000
+```
+
+The following flags values are not empty:
+
+```rust
+0b0000_0001
+0b0110_0000
+```
+
+#### All
+
+Whether all defined flags are contained in a flags value.
+
+----
+
+Given a flags type:
+
+```rust
+struct Flags {
+    const A   = 0b0000_0001;
+    const B   = 0b0000_0010;
+}
+```
+
+the following flags values all satisfy all:
+
+```rust
+0b0000_0011
+0b1000_0011
+0b1111_1111
+```
+
+### Operations
+
+Examples in this section all use the given flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0001;
+    const B = 0b0000_0010;
+    const C = 0b0000_1100;
+}
+```
+
+#### Truncate
+
+Unset all unknown bits in a flags value.
+
+----
+
+Given the flags value:
+
+```rust
+0b1111_1111
+```
+
+the result of truncation will be:
+
+```rust
+0b0000_1111
+```
+
+----
+
+Truncating doesn't guarantee that a non-empty result will contain any defined flags. Given the following flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0101;
+}
+```
+
+and the following flags value:
+
+```rust
+0b0000_1110;
+```
+
+The result of truncation will be:
+
+```rust
+0b0000_0100;
+```
+
+which intersects the flag `A`, but doesn't contain it.
+
+This behavior is possible even when only operating with flags values containing defined flags. Given the following flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0101;
+    const B = 0b0000_0001;
+}
+```
+
+The result of `A ^ B` is `0b0000_0100`, which also doesn't contain any defined flag.
+
+----
+
+If all known bits are in the set of at least one defined single-bit flag, then all operations that produce non-empty results will always contain defined flags.
+
+#### Union
+
+The bitwise or (`|`) of the bits in two flags values.
+
+----
+
+The following are examples of the result of unioning flags values:
+
+```rust
+0b0000_0001 | 0b0000_0010 = 0b0000_0011
+0b0000_0000 | 0b1111_1111 = 0b1111_1111
+```
+
+#### Intersection
+
+The bitwise and (`&`) of the bits in two flags values.
+
+----
+
+The following are examples of the result of intersecting flags values:
+
+```rust
+0b0000_0001 & 0b0000_0010 = 0b0000_0000
+0b1111_1100 & 0b1111_0111 = 0b1111_0100
+0b1111_1111 & 0b1111_1111 = 0b1111_1111
+```
+
+#### Symmetric difference
+
+The bitwise exclusive-or (`^`) of the bits in two flags values.
+
+----
+
+The following are examples of the symmetric difference between two flags values:
+
+```rust
+0b0000_0001 ^ 0b0000_0010 = 0b0000_0011
+0b0000_1111 ^ 0b0000_0011 = 0b0000_1100
+0b1100_0000 ^ 0b0011_0000 = 0b1111_0000
+```
+
+#### Complement
+
+The bitwise negation (`!`) of the bits in a flags value, truncating the result.
+
+----
+
+The following are examples of the complement of a flags value:
+
+```rust
+!0b0000_0000 = 0b0000_1111
+!0b0000_1111 = 0b0000_0000
+!0b1111_1000 = 0b0000_0111
+```
+
+#### Difference
+
+The bitwise union (`|`) of the bits in one flags value and the bitwise negation (`!`) of the bits in another.
+
+----
+
+This operation is not equivalent to the intersection of one flags value with the complement of another (`&!`).
+The former will truncate the result, where difference will not.
+
+----
+
+The following are examples of the difference between two flags values:
+
+```rust
+0b0000_0001 & !0b0000_0010 = 0b0000_0001
+0b0000_1101 & !0b0000_0011 = 0b0000_1100
+0b1111_1111 & !0b0000_0001 = 0b1111_1110
+```
+
+### Iteration
+
+Yield the bits of a source flags value in a set of contained flags values.
+
+----
+
+To be most useful, each yielded flags value should set exactly the bits of a defined flag contained in the source. Any known bits that aren't in the set of any contained flag should be yielded together as a final flags value.
+
+----
+
+Given the following flags type:
+
+```rust
+struct Flags {
+    const A  = 0b0000_0001;
+    const B  = 0b0000_0010;
+    const AB = 0b0000_0011;
+}
+```
+
+and the following flags value:
+
+```rust
+0b0000_1111
+```
+
+When iterated it may yield a flags value for `A` and `B`, then a final flag with the unknown bits:
+
+```rust
+0b0000_0001
+0b0000_0010
+0b0000_1100
+```
+
+It may also yield a flags value for `AB`, then a final flag with the unknown bits:
+
+```rust
+0b0000_0011
+0b0000_1100
+```
+
+----
+
+Given the following flags type:
+
+```rust
+struct Flags {
+    const A = 0b0000_0011;
+}
+```
+
+and the following flags value:
+
+```rust
+0b0000_0001
+```
+
+When iterated it will still yield a flags value for the known bit `0b0000_0001` even though it doesn't contain a flag.
+
+### Formatting
+
+Format and parse a flags value as text using the following grammar:
+
+- _Flags:_ (_Whitespace_ _Flag_ _Whitespace_)`|`*
+- _Flag:_ _Name_ | _Hex Number_
+- _Name:_ The name of any defined flag
+- _Hex Number_: `0x`([0-9a-fA-F])*
+- _Whitespace_: (\s)*
+
+Flags values can be formatted as _Flags_ by iterating over them, formatting each yielded flags value as a _Flag_. Any yielded flags value that sets exactly the bits of a defined flag with a name should be formatted as a _Name_. Otherwise it must be formatted as a _Hex Number_.
+
+Formatting and parsing supports three modes:
+
+- **Retain**: Formatting and parsing roundtrips exactly the bits of the source flags value. This is the default behavior.
+- **Truncate**: Flags values are truncated before formatting, and truncated after parsing.
+- **Strict**: A _Flag_ may only be formatted and parsed as a _Name_. _Hex numbers_ are not allowed. A consequence of this is that unknown bits and any bits that aren't in a contained named flag will be ignored. This is recommended for flags values serialized across API boundaries, like web services.
+
+Text that is empty or whitespace is an empty flags value.
+
+----
+
+Given the following flags type:
+
+```rust
+struct Flags {
+    const A  = 0b0000_0001;
+    const B  = 0b0000_0010;
+    const AB = 0b0000_0011;
+    const C  = 0b0000_1100;
+}
+```
+
+The following are examples of how flags values can be formatted using any mode:
+
+```rust
+0b0000_0000 = ""
+0b0000_0001 = "A"
+0b0000_0010 = "B"
+0b0000_0011 = "A | B"
+0b0000_0011 = "AB"
+0b0000_1111 = "A | B | C"
+```
+
+Truncate mode will unset any unknown bits:
+
+```rust
+0b1000_0000 = ""
+0b1111_1111 = "A | B | C"
+0b0000_1000 = "0x8"
+```
+
+Retain mode will include any unknown bits as a final _Flag_:
+
+```rust
+0b1000_0000 = "0x80"
+0b1111_1111 = "A | B | C | 0xf0"
+0b0000_1000 = "0x8"
+```
+
+Strict mode will unset any unknown bits, as well as bits not contained in any defined named flags:
+
+```rust
+0b1000_0000 = ""
+0b1111_1111 = "A | B | C"
+0b0000_1000 = ""
+```
diff --git a/src/example_generated.rs b/src/example_generated.rs
index 7f8a5c5..abb1118 100644
--- a/src/example_generated.rs
+++ b/src/example_generated.rs
@@ -21,16 +21,16 @@
         // Field `A`.
         ///
         /// This flag has the value `0b00000001`.
-        A = 0b00000001;
+        const A = 0b00000001;
         /// Field `B`.
         ///
         /// This flag has the value `0b00000010`.
-        B = 0b00000010;
+        const B = 0b00000010;
         /// Field `C`.
         ///
         /// This flag has the value `0b00000100`.
-        C = 0b00000100;
-        ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+        const C = 0b00000100;
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
     }
 }
 
@@ -38,6 +38,10 @@
     Flags: u32, Field0
 }
 
+__impl_public_bitflags_ops! {
+    Flags
+}
+
 __impl_public_bitflags_iter! {
     Flags: u32, Flags
 }
@@ -47,15 +51,15 @@
         /// Field `A`.
         ///
         /// This flag has the value `0b00000001`.
-        A = 0b00000001;
+        const A = 0b00000001;
         /// Field `B`.
         ///
         /// This flag has the value `0b00000010`.
-        B = 0b00000010;
+        const B = 0b00000010;
         /// Field `C`.
         ///
         /// This flag has the value `0b00000100`.
-        C = 0b00000100;
-        ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+        const C = 0b00000100;
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
     }
 }
diff --git a/src/external.rs b/src/external.rs
index 103b5d1..716af83 100644
--- a/src/external.rs
+++ b/src/external.rs
@@ -14,15 +14,15 @@
 Next, define a macro like so:
 
 ```rust
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(feature = "serde")]
 macro_rules! __impl_external_bitflags_my_library {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {
@@ -30,15 +30,15 @@
     };
 }
 
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(not(feature = "my_library"))]
 macro_rules! __impl_external_bitflags_my_library {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {};
@@ -57,8 +57,8 @@
 __impl_external_bitflags_my_library! {
     $InternalBitFlags: $T, $PublicBitFlags {
         $(
-            $(#[$attr $($args)*])*
-            $Flag;
+            $(#[$inner $($args)*])*
+            const $Flag;
         )*
     }
 }
@@ -77,14 +77,14 @@
 }
 
 /// Implements traits from external libraries for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_external_bitflags {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {
@@ -92,29 +92,29 @@
         // Use `serde` as an example: generate code when the feature is available,
         // and a no-op when it isn't
 
-        __impl_external_bitflags_serde! {
+        $crate::__impl_external_bitflags_serde! {
             $InternalBitFlags: $T, $PublicBitFlags {
                 $(
-                    $(#[$attr $($args)*])*
-                    $Flag;
+                    $(#[$inner $($args)*])*
+                    const $Flag;
                 )*
             }
         }
 
-        __impl_external_bitflags_arbitrary! {
+        $crate::__impl_external_bitflags_arbitrary! {
             $InternalBitFlags: $T, $PublicBitFlags {
                 $(
-                    $(#[$attr $($args)*])*
-                    $Flag;
+                    $(#[$inner $($args)*])*
+                    const $Flag;
                 )*
             }
         }
 
-        __impl_external_bitflags_bytemuck! {
+        $crate::__impl_external_bitflags_bytemuck! {
             $InternalBitFlags: $T, $PublicBitFlags {
                 $(
-                    $(#[$attr $($args)*])*
-                    $Flag;
+                    $(#[$inner $($args)*])*
+                    const $Flag;
                 )*
             }
         }
@@ -125,15 +125,15 @@
 pub mod serde;
 
 /// Implement `Serialize` and `Deserialize` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(feature = "serde")]
 macro_rules! __impl_external_bitflags_serde {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {
@@ -153,9 +153,7 @@
             fn deserialize<D: $crate::__private::serde::Deserializer<'de>>(
                 deserializer: D,
             ) -> $crate::__private::core::result::Result<Self, D::Error> {
-                let flags: $PublicBitFlags = $crate::serde::deserialize(
-                    deserializer,
-                )?;
+                let flags: $PublicBitFlags = $crate::serde::deserialize(deserializer)?;
 
                 Ok(flags.0)
             }
@@ -163,15 +161,15 @@
     };
 }
 
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(not(feature = "serde"))]
 macro_rules! __impl_external_bitflags_serde {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {};
@@ -184,15 +182,15 @@
 mod bytemuck;
 
 /// Implement `Arbitrary` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(feature = "arbitrary")]
 macro_rules! __impl_external_bitflags_arbitrary {
     (
             $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
                 $(
-                    $(#[$attr:ident $($args:tt)*])*
-                    $Flag:ident;
+                    $(#[$inner:ident $($args:tt)*])*
+                    const $Flag:tt;
                 )*
             }
     ) => {
@@ -206,62 +204,58 @@
     };
 }
 
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(not(feature = "arbitrary"))]
 macro_rules! __impl_external_bitflags_arbitrary {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {};
 }
 
 /// Implement `Pod` and `Zeroable` for the internal bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(feature = "bytemuck")]
 macro_rules! __impl_external_bitflags_bytemuck {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {
         // SAFETY: $InternalBitFlags is guaranteed to have the same ABI as $T,
         // and $T implements Pod
-        unsafe impl $crate::__private::bytemuck::Pod for $InternalBitFlags
-        where
-            $T: $crate::__private::bytemuck::Pod,
+        unsafe impl $crate::__private::bytemuck::Pod for $InternalBitFlags where
+            $T: $crate::__private::bytemuck::Pod
         {
-
         }
 
         // SAFETY: $InternalBitFlags is guaranteed to have the same ABI as $T,
         // and $T implements Zeroable
-        unsafe impl $crate::__private::bytemuck::Zeroable for $InternalBitFlags
-        where
-            $T: $crate::__private::bytemuck::Zeroable,
+        unsafe impl $crate::__private::bytemuck::Zeroable for $InternalBitFlags where
+            $T: $crate::__private::bytemuck::Zeroable
         {
-
         }
     };
 }
 
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 #[cfg(not(feature = "bytemuck"))]
 macro_rules! __impl_external_bitflags_bytemuck {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt;
             )*
         }
     ) => {};
diff --git a/src/external/arbitrary.rs b/src/external/arbitrary.rs
index ae59677..ea76f0a 100644
--- a/src/external/arbitrary.rs
+++ b/src/external/arbitrary.rs
@@ -2,12 +2,12 @@
 
 use crate::Flags;
 
-/// Get a random known flags value.
-pub fn arbitrary<'a, B: Flags>(
-    u: &mut arbitrary::Unstructured<'a>,
-) -> arbitrary::Result<B>
+/**
+Generate some arbitrary flags value with only known bits set.
+*/
+pub fn arbitrary<'a, B: Flags>(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<B>
 where
-    B::Bits: arbitrary::Arbitrary<'a>
+    B::Bits: arbitrary::Arbitrary<'a>,
 {
     B::from_bits(u.arbitrary()?).ok_or_else(|| arbitrary::Error::IncorrectFormat)
 }
diff --git a/src/external/bytemuck.rs b/src/external/bytemuck.rs
index 5ab109e..a0cd68c 100644
--- a/src/external/bytemuck.rs
+++ b/src/external/bytemuck.rs
@@ -1,7 +1,7 @@
 #[cfg(test)]
 mod tests {
     use bytemuck::{Pod, Zeroable};
-    
+
     bitflags! {
         #[derive(Pod, Zeroable, Clone, Copy)]
         #[repr(transparent)]
diff --git a/src/external/serde.rs b/src/external/serde.rs
index bc1f2ec..be4f2ed 100644
--- a/src/external/serde.rs
+++ b/src/external/serde.rs
@@ -1,17 +1,21 @@
 //! Specialized serialization for flags types using `serde`.
 
+use crate::{
+    parser::{self, ParseHex, WriteHex},
+    Flags,
+};
 use core::{fmt, str};
-use crate::{Flags, parser::{self, ParseHex, WriteHex}};
 use serde::{
     de::{Error, Visitor},
     Deserialize, Deserializer, Serialize, Serializer,
 };
 
-/// 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>
+/**
+Serialize a set of flags as a human-readable string or their underlying bits.
+
+Any unknown bits will be retained.
+*/
+pub fn serialize<B: Flags, S: Serializer>(flags: &B, serializer: S) -> Result<S::Ok, S::Error>
 where
     B::Bits: WriteHex + Serialize,
 {
@@ -25,14 +29,12 @@
     }
 }
 
-/// Deserialize a set of flags from a human-readable string or their underlying bits.
-pub fn deserialize<
-    'de,
-    B: Flags,
-    D: Deserializer<'de>,
->(
-    deserializer: D,
-) -> Result<B, D::Error>
+/**
+Deserialize a set of flags from a human-readable string or their underlying bits.
+
+Any unknown bits will be retained.
+*/
+pub fn deserialize<'de, B: Flags, D: Deserializer<'de>>(deserializer: D) -> Result<B, D::Error>
 where
     B::Bits: ParseHex + Deserialize<'de>,
 {
diff --git a/src/internal.rs b/src/internal.rs
index c4fb653..87d01cc 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -6,7 +6,7 @@
 /// Declare the `bitflags`-facing bitflags struct.
 ///
 /// This type is part of the `bitflags` crate's public API, but not part of the user's.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __declare_internal_bitflags {
     (
@@ -25,14 +25,14 @@
 ///
 /// Methods and trait implementations can be freely added here without breaking end-users.
 /// If we want to expose new functionality to `#[derive]`, this is the place to do it.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_internal_bitflags {
     (
         $InternalBitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident = $value:expr;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt = $value:expr;
             )*
         }
     ) => {
@@ -56,7 +56,7 @@
                 if self.is_empty() {
                     // If no flags are set then write an empty hex flag to avoid
                     // writing an empty string. In some contexts, like serialization,
-                    // an empty string is preferrable, but it may be unexpected in
+                    // an empty string is preferable, but it may be unexpected in
                     // others for a format not to produce any output.
                     //
                     // We can remove this `0x0` and remain compatible with `FromStr`,
@@ -97,16 +97,20 @@
 
         // The internal flags type offers a similar API to the public one
 
-        __impl_public_bitflags! {
+        $crate::__impl_public_bitflags! {
             $InternalBitFlags: $T, $PublicBitFlags {
                 $(
-                    $(#[$attr $($args)*])*
-                    $Flag;
+                    $(#[$inner $($args)*])*
+                    const $Flag = $value;
                 )*
             }
         }
 
-        __impl_public_bitflags_iter! {
+        $crate::__impl_public_bitflags_ops! {
+            $InternalBitFlags
+        }
+
+        $crate::__impl_public_bitflags_iter! {
             $InternalBitFlags: $T, $PublicBitFlags
         }
 
diff --git a/src/iter.rs b/src/iter.rs
index 4b6210e..7f7ce55 100644
--- a/src/iter.rs
+++ b/src/iter.rs
@@ -1,18 +1,21 @@
-//! Iterating over set flag values.
+/*!
+Yield the bits of a source flags value in a set of contained flags values.
+*/
 
-use crate::{Flags, Flag};
+use crate::{Flag, Flags};
 
-/// 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.
+/**
+An iterator over flags values.
+
+This iterator will yield flags values for contained, defined flags first, with any remaining bits yielded
+as a final flags value.
+*/
 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),
@@ -22,10 +25,11 @@
 }
 
 impl<B: 'static> Iter<B> {
+    // Used by the `bitflags` macro
     #[doc(hidden)]
-    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, state: B) -> Self {
+    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
         Iter {
-            inner: IterNames::__private_const_new(flags, source, state),
+            inner: IterNames::__private_const_new(flags, source, remaining),
             done: false,
         }
     }
@@ -33,18 +37,18 @@
 
 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()))
+                    Some(B::from_bits_retain(self.inner.remaining.bits()))
                 } else {
                     None
                 }
@@ -54,80 +58,88 @@
     }
 }
 
-/// An iterator over a set of flags and their names.
-///
-/// Any bits that don't correspond to a valid flag will be ignored.
+/**
+An iterator over flags values.
+
+This iterator only yields flags values for contained, defined, named flags. Any remaining bits
+won't be yielded, but can be found with the [`IterNames::remaining`] method.
+*/
 pub struct IterNames<B: 'static> {
     flags: &'static [Flag<B>],
     idx: usize,
     source: B,
-    state: B,
+    remaining: 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()),
+            remaining: B::from_bits_retain(flags.bits()),
             source: B::from_bits_retain(flags.bits()),
         }
     }
 }
 
 impl<B: 'static> IterNames<B> {
+    // Used by the bitflags macro
     #[doc(hidden)]
-    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, state: B) -> Self {
+    pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
         IterNames {
             flags,
             idx: 0,
-            state,
+            remaining,
             source,
         }
     }
 
-    /// Get the remaining (unyielded) flags.
+    /// Get a flags value of any remaining bits that haven't been yielded yet.
     ///
     /// 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.
+    /// to a contained, defined, named flag remaining.
     pub fn remaining(&self) -> &B {
-        &self.state
+        &self.remaining
     }
 }
 
 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() {
+            if self.remaining.is_empty() {
                 return None;
             }
 
             self.idx += 1;
 
+            // Skip unnamed flags
+            if flag.name().is_empty() {
+                continue;
+            }
+
             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:
+            // If the flag is set in the original source _and_ it has bits that haven't
+            // been covered by a previous flag yet then yield it. These conditions cover
+            // two cases for multi-bit flags:
             //
-            // 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));
+            // 1. When flags partially overlap, such as `0b00000001` and `0b00000101`, we'll
+            // yield both flags.
+            // 2. When flags fully overlap, such as in convenience flags that are a shorthand for others,
+            // we won't yield both flags.
+            if self.source.contains(B::from_bits_retain(bits))
+                && self.remaining.intersects(B::from_bits_retain(bits))
+            {
+                self.remaining.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 37d5540..18270f7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,425 +8,243 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A typesafe bitmask flag generator useful for sets of C-style flags.
-//! It can be used for creating ergonomic wrappers around C APIs.
-//!
-//! The `bitflags!` macro generates `struct`s that manage a set of flags. The
-//! type of those flags must be some primitive integer.
-//!
-//! # Examples
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!         const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let e1 = Flags::A | Flags::C;
-//!     let e2 = Flags::B | Flags::C;
-//!     assert_eq!((e1 | e2), Flags::ABC);   // union
-//!     assert_eq!((e1 & e2), Flags::C);     // intersection
-//!     assert_eq!((e1 - e2), Flags::A);     // set difference
-//!     assert_eq!(!e2, Flags::A);           // set complement
-//! }
-//! ```
-//!
-//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code
-//! generated by the above `bitflags!` expansion.
-//!
-//! # Visibility
-//!
-//! The `bitflags!` macro supports visibility, just like you'd expect when writing a normal
-//! Rust `struct`:
-//!
-//! ```
-//! mod example {
-//!     use bitflags::bitflags;
-//!
-//!     bitflags! {
-//!         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!         pub struct Flags1: u32 {
-//!             const A = 0b00000001;
-//!         }
-//!
-//!         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//! #       pub
-//!         struct Flags2: u32 {
-//!             const B = 0b00000010;
-//!         }
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let flag1 = example::Flags1::A;
-//!     let flag2 = example::Flags2::B; // error: const `B` is private
-//! }
-//! ```
-//!
-//! # Attributes
-//!
-//! Attributes can be attached to the generated flags types and their constants as normal.
-//!
-//! # Representation
-//!
-//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a generated flags type.
-//! The generated flags type is always guaranteed to be a newtype where its only field has the same
-//! ABI as the underlying integer type.
-//!
-//! In this example, `Flags` has the same ABI as `u32`:
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[repr(transparent)]
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//! ```
-//!
-//! # Extending
-//!
-//! Generated flags types belong to you, so you can add trait implementations to them outside
-//! of what the `bitflags!` macro gives:
-//!
-//! ```
-//! use std::fmt;
-//!
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!     }
-//! }
-//!
-//! impl Flags {
-//!     pub fn clear(&mut self) {
-//!         *self.0.bits_mut() = 0;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let mut flags = Flags::A | Flags::B;
-//!
-//!     flags.clear();
-//!     assert!(flags.is_empty());
-//!
-//!     assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)");
-//!     assert_eq!(format!("{:?}", Flags::B), "Flags(B)");
-//! }
-//! ```
-//!
-//! # What's implemented by `bitflags!`
-//!
-//! The `bitflags!` macro adds some trait implementations and inherent methods
-//! to generated flags types, but leaves room for you to choose the semantics
-//! of others.
-//!
-//! ## Iterators
-//!
-//! The following iterator traits are implemented for generated flags types:
-//!
-//! - `Extend`: adds the union of the instances iterated over.
-//! - `FromIterator`: calculates the union.
-//! - `IntoIterator`: iterates over set flag values.
-//!
-//! ## Formatting
-//!
-//! The following formatting traits are implemented for generated flags types:
-//!
-//! - `Binary`.
-//! - `LowerHex` and `UpperHex`.
-//! - `Octal`.
-//!
-//! Also see the _Debug and Display_ section for details about standard text
-//! representations for flags types.
-//!
-//! ## Operators
-//!
-//! The following operator traits are implemented for the generated `struct`s:
-//!
-//! - `BitOr` and `BitOrAssign`: union
-//! - `BitAnd` and `BitAndAssign`: intersection
-//! - `BitXor` and `BitXorAssign`: toggle
-//! - `Sub` and `SubAssign`: set difference
-//! - `Not`: set complement
-//!
-//! ## Methods
-//!
-//! The following methods are defined for the generated `struct`s:
-//!
-//! - `empty`: an empty set of flags
-//! - `all`: the set of all defined flags
-//! - `bits`: the raw value of the flags currently stored
-//! - `from_bits`: convert from underlying bit representation, unless that
-//!                representation contains bits that do not correspond to a
-//!                defined flag
-//! - `from_bits_truncate`: convert from underlying bit representation, dropping
-//!                         any bits that do not correspond to defined flags
-//! - `from_bits_retain`: convert from underlying bit representation, keeping
-//!                          all bits (even those not corresponding to defined
-//!                          flags)
-//! - `is_empty`: `true` if no flags are currently stored
-//! - `is_all`: `true` if currently set flags exactly equal all defined flags
-//! - `intersects`: `true` if there are flags common to both `self` and `other`
-//! - `contains`: `true` if all of the flags in `other` are contained within `self`
-//! - `insert`: inserts the specified flags in-place
-//! - `remove`: removes the specified flags in-place
-//! - `toggle`: the specified flags will be inserted if not present, and removed
-//!             if they are.
-//! - `set`: inserts or removes the specified flags depending on the passed value
-//! - `intersection`: returns a new set of flags, containing only the flags present
-//!                   in both `self` and `other` (the argument to the function).
-//! - `union`: returns a new set of flags, containing any flags present in
-//!            either `self` or `other` (the argument to the function).
-//! - `difference`: returns a new set of flags, containing all flags present in
-//!                 `self` without any of the flags present in `other` (the
-//!                 argument to the function).
-//! - `symmetric_difference`: returns a new set of flags, containing all flags
-//!                           present in either `self` or `other` (the argument
-//!                           to the function), but not both.
-//! - `complement`: returns a new set of flags, containing all flags which are
-//!                 not set in `self`, but which are allowed for this type.
-//!
-//! # What's not implemented by `bitflags!`
-//!
-//! Some functionality is not automatically implemented for generated flags types
-//! by the `bitflags!` macro, even when it reasonably could be. This is so callers
-//! have more freedom to decide on the semantics of their flags types.
-//!
-//! ## `Clone` and `Copy`
-//!
-//! Generated flags types are not automatically copyable, even though they can always
-//! derive both `Clone` and `Copy`.
-//!
-//! ## `Default`
-//!
-//! The `Default` trait is not automatically implemented for the generated structs.
-//!
-//! If your default value is equal to `0` (which is the same value as calling `empty()`
-//! on the generated struct), you can simply derive `Default`:
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     // Results in default value with bits: 0
-//!     #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let derived_default: Flags = Default::default();
-//!     assert_eq!(derived_default.bits(), 0);
-//! }
-//! ```
-//!
-//! If your default value is not equal to `0` you need to implement `Default` yourself:
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//!
-//! // explicit `Default` implementation
-//! impl Default for Flags {
-//!     fn default() -> Flags {
-//!         Flags::A | Flags::C
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let implemented_default: Flags = Default::default();
-//!     assert_eq!(implemented_default, (Flags::A | Flags::C));
-//! }
-//! ```
-//!
-//! ## `Debug` and `Display`
-//!
-//! The `Debug` trait can be derived for a reasonable implementation. This library defines a standard
-//! text-based representation for flags that generated flags types can use. For details on the exact
-//! grammar, see the [`parser`] module.
-//!
-//! To support formatting and parsing your generated flags types using that representation, you can implement
-//! the standard `Display` and `FromStr` traits in this fashion:
-//!
-//! ```
-//! use bitflags::bitflags;
-//! use std::{fmt, str};
-//!
-//! bitflags! {
-//!     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()?))
-//!     }
-//! }
-//! ```
-//!
-//! ## `PartialEq` and `PartialOrd`
-//!
-//! Equality and ordering can be derived for a reasonable implementation, or implemented manually
-//! for different semantics.
-//!
-//! # Edge cases
-//!
-//! ## Zero Flags
-//!
-//! Flags with a value equal to zero will have some strange behavior that one should be aware of.
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const NONE = 0b00000000;
-//!         const SOME = 0b00000001;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let empty = Flags::empty();
-//!     let none = Flags::NONE;
-//!     let some = Flags::SOME;
-//!
-//!     // Zero flags are treated as always present
-//!     assert!(empty.contains(Flags::NONE));
-//!     assert!(none.contains(Flags::NONE));
-//!     assert!(some.contains(Flags::NONE));
-//!
-//!     // Zero flags will be ignored when testing for emptiness
-//!     assert!(none.is_empty());
-//! }
-//! ```
-//!
-//! Users should generally avoid defining a flag with a value of zero.
-//!
-//! ## Multi-bit Flags
-//!
-//! It is allowed to define a flag with multiple bits set, however such
-//! flags are _not_ treated as a set where any of those bits is a valid
-//! flag. Instead, each flag is treated as a unit when converting from
-//! bits with [`from_bits`] or [`from_bits_truncate`].
-//!
-//! ```
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u8 {
-//!         const F3 = 0b00000011;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     // This bit pattern does not set all the bits in `F3`, so it is rejected.
-//!     assert!(Flags::from_bits(0b00000001).is_none());
-//!     assert!(Flags::from_bits_truncate(0b00000001).is_empty());
-//! }
-//! ```
-//!
-//! [`from_bits`]: Flags::from_bits
-//! [`from_bits_truncate`]: Flags::from_bits_truncate
-//!
-//! # The `Flags` trait
-//!
-//! 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::Flags>(flags: &F) -> usize {
-//!     // Find out how many flags there are in total
-//!     let total = F::all().iter().count();
-//!
-//!     // Find out how many flags are set
-//!     let set = flags.iter().count();
-//!
-//!     total - set
-//! }
-//!
-//! use bitflags::bitflags;
-//!
-//! bitflags! {
-//!     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//!
-//! assert_eq!(2, count_unset_flags(&Flags::B));
-//! ```
-//!
-//! # The internal field
-//!
-//! This library generates newtypes like:
-//!
-//! ```
-//! # pub struct Field0;
-//! pub struct Flags(Field0);
-//! ```
-//!
-//! You can freely use methods and trait implementations on this internal field as `.0`.
-//! For details on exactly what's generated for it, see the [`Field0`](example_generated/struct.Field0.html)
-//! example docs.
+/*!
+Generate types for C-style flags with ergonomic APIs.
+
+# Getting started
+
+Add `bitflags` to your `Cargo.toml`:
+
+```toml
+[dependencies.bitflags]
+version = "2.4.2"
+```
+
+## Generating flags types
+
+Use the [`bitflags`] macro to generate flags types:
+
+```rust
+use bitflags::bitflags;
+
+bitflags! {
+    pub struct Flags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+    }
+}
+```
+
+See the docs for the `bitflags` macro for the full syntax.
+
+Also see the [`example_generated`] module for an example of what the `bitflags` macro generates for a flags type.
+
+### Externally defined flags
+
+If you're generating flags types for an external source, such as a C API, you can define
+an extra unnamed flag as a mask of all bits the external source may ever set. Usually this would be all bits (`!0`):
+
+```rust
+# use bitflags::bitflags;
+bitflags! {
+    pub struct Flags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+
+        // The source may set any bits
+        const _ = !0;
+    }
+}
+```
+
+Why should you do this? Generated methods like `all` and truncating operators like `!` only consider
+bits in defined flags. Adding an unnamed flag makes those methods consider additional bits,
+without generating additional constants for them. It helps compatibility when the external source
+may start setting additional bits at any time. The [known and unknown bits](#known-and-unknown-bits)
+section has more details on this behavior.
+
+### Custom derives
+
+You can derive some traits on generated flags types if you enable Cargo features. The following
+libraries are currently supported:
+
+- `serde`: Support `#[derive(Serialize, Deserialize)]`, using text for human-readable formats,
+and a raw number for binary formats.
+- `arbitrary`: Support `#[derive(Arbitrary)]`, only generating flags values with known bits.
+- `bytemuck`: Support `#[derive(Pod, Zeroable)]`, for casting between flags values and their
+underlying bits values.
+
+You can also define your own flags type outside of the [`bitflags`] macro and then use it to generate methods.
+This can be useful if you need a custom `#[derive]` attribute for a library that `bitflags` doesn't
+natively support:
+
+```rust
+# use std::fmt::Debug as SomeTrait;
+# use bitflags::bitflags;
+#[derive(SomeTrait)]
+pub struct Flags(u32);
+
+bitflags! {
+    impl Flags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+    }
+}
+```
+
+### Adding custom methods
+
+The [`bitflags`] macro supports attributes on generated flags types within the macro itself, while
+`impl` blocks can be added outside of it:
+
+```rust
+# use bitflags::bitflags;
+bitflags! {
+    // Attributes can be applied to flags types
+    #[repr(transparent)]
+    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+    pub struct Flags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+    }
+}
+
+// Impl blocks can be added to flags types
+impl Flags {
+    pub fn as_u64(&self) -> u64 {
+        self.bits() as u64
+    }
+}
+```
+
+## Working with flags values
+
+Use generated constants and standard bitwise operators to interact with flags values:
+
+```rust
+# use bitflags::bitflags;
+# bitflags! {
+#     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#     pub struct Flags: u32 {
+#         const A = 0b00000001;
+#         const B = 0b00000010;
+#         const C = 0b00000100;
+#     }
+# }
+// union
+let ab = Flags::A | Flags::B;
+
+// intersection
+let a = ab & Flags::A;
+
+// difference
+let b = ab - Flags::A;
+
+// complement
+let c = !ab;
+```
+
+See the docs for the [`Flags`] trait for more details on operators and how they behave.
+
+# Formatting and parsing
+
+`bitflags` defines a text format that can be used to convert any flags value to and from strings.
+
+See the [`parser`] module for more details.
+
+# Specification
+
+The terminology and behavior of generated flags types is
+[specified in the source repository](https://github.com/bitflags/bitflags/blob/main/spec.md).
+Details are repeated in these docs where appropriate, but is exhaustively listed in the spec. Some
+things are worth calling out explicitly here.
+
+## Flags types, flags values, flags
+
+The spec and these docs use consistent terminology to refer to things in the bitflags domain:
+
+- **Bits type**: A type that defines a fixed number of bits at specific locations.
+- **Flag**: A set of bits in a bits type that may have a unique name.
+- **Flags type**: A set of defined flags over a specific bits type.
+- **Flags value**: An instance of a flags type using its specific bits value for storage.
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct FlagsType: u8 {
+//                    -- Bits type
+//         --------- Flags type
+        const A = 1;
+//            ----- Flag
+    }
+}
+
+let flag = FlagsType::A;
+//  ---- Flags value
+```
+
+## Known and unknown bits
+
+Any bits in a flag you define are called _known bits_. Any other bits are _unknown bits_.
+In the following flags type:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+        const C = 1 << 2;
+    }
+}
+```
+
+The known bits are `0b0000_0111` and the unknown bits are `0b1111_1000`.
+
+`bitflags` doesn't guarantee that a flags value will only ever have known bits set, but some operators
+will unset any unknown bits they encounter. In a future version of `bitflags`, all operators will
+unset unknown bits.
+
+If you're using `bitflags` for flags types defined externally, such as from C, you probably want all
+bits to be considered known, in case that external source changes. You can do this using an unnamed
+flag, as described in [externally defined flags](#externally-defined-flags).
+
+## Zero-bit flags
+
+Flags with no bits set should be avoided because they interact strangely with [`Flags::contains`]
+and [`Flags::intersects`]. A zero-bit flag is always contained, but is never intersected. The
+names of zero-bit flags can be parsed, but are never formatted.
+
+## Multi-bit flags
+
+Flags that set multiple bits should be avoided unless each bit is also in a single-bit flag.
+Take the following flags type as an example:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const A = 1;
+        const B = 1 | 1 << 1;
+    }
+}
+```
+
+The result of `Flags::A ^ Flags::B` is `0b0000_0010`, which doesn't correspond to either
+`Flags::A` or `Flags::B` even though it's still a known bit.
+*/
 
 // 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.3.2")]
+#![cfg_attr(test, allow(mixed_script_confusables))]
 
 #[doc(inline)]
-pub use traits::{Flags, Flag, Bits};
+pub use traits::{Bits, Flag, Flags};
 
 pub mod iter;
 pub mod parser;
@@ -435,6 +253,7 @@
 
 #[doc(hidden)]
 pub mod __private {
+    #[allow(unused_imports)] // Easier than conditionally checking any optional external dependencies
     pub use crate::{external::__private::*, traits::__private::*};
 
     pub use core;
@@ -497,71 +316,141 @@
 - `external`: where external library traits are implemented conditionally.
 */
 
-/// The macro used to generate the flag structure.
-///
-/// See the [crate level docs](../bitflags/index.html) for complete documentation.
-///
-/// # Example
-///
-/// ```
-/// use bitflags::bitflags;
-///
-/// bitflags! {
-///     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-///     struct Flags: u32 {
-///         const A = 0b00000001;
-///         const B = 0b00000010;
-///         const C = 0b00000100;
-///         const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
-///     }
-/// }
-///
-/// let e1 = Flags::A | Flags::C;
-/// let e2 = Flags::B | Flags::C;
-/// assert_eq!((e1 | e2), Flags::ABC);   // union
-/// assert_eq!((e1 & e2), Flags::C);     // intersection
-/// assert_eq!((e1 - e2), Flags::A);     // set difference
-/// assert_eq!(!e2, Flags::A);           // set complement
-/// ```
-///
-/// The generated `struct`s can also be extended with type and trait
-/// implementations:
-///
-/// ```
-/// use std::fmt;
-///
-/// use bitflags::bitflags;
-///
-/// bitflags! {
-///     #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-///     struct Flags: u32 {
-///         const A = 0b00000001;
-///         const B = 0b00000010;
-///     }
-/// }
-///
-/// impl Flags {
-///     pub fn clear(&mut self) {
-///         *self.0.bits_mut() = 0;
-///     }
-/// }
-///
-/// let mut flags = Flags::A | Flags::B;
-///
-/// flags.clear();
-/// assert!(flags.is_empty());
-///
-/// assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)");
-/// assert_eq!(format!("{:?}", Flags::B), "Flags(B)");
-/// ```
-#[macro_export(local_inner_macros)]
+/**
+Generate a flags type.
+
+# `struct` mode
+
+A declaration that begins with `$vis struct` will generate a `struct` for a flags type, along with
+methods and trait implementations for it. The body of the declaration defines flags as constants,
+where each constant is a flags value of the generated flags type.
+
+## Examples
+
+Generate a flags type using `u8` as the bits type:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+        const C = 0b0000_0100;
+    }
+}
+```
+
+Flags types are private by default and accept standard visibility modifiers. Flags themselves
+are always public:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    pub struct Flags: u8 {
+        // Constants are always `pub`
+        const A = 1;
+    }
+}
+```
+
+Flags may refer to other flags using their [`Flags::bits`] value:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+        const AB = Flags::A.bits() | Flags::B.bits();
+    }
+}
+```
+
+A single `bitflags` invocation may include zero or more flags type declarations:
+
+```
+# use bitflags::bitflags;
+bitflags! {}
+
+bitflags! {
+    struct Flags1: u8 {
+        const A = 1;
+    }
+
+    struct Flags2: u8 {
+        const A = 1;
+    }
+}
+```
+
+# `impl` mode
+
+A declaration that begins with `impl` will only generate methods and trait implementations for the
+`struct` defined outside of the `bitflags` macro.
+
+The struct itself must be a newtype using the bits type as its field.
+
+The syntax for `impl` mode is identical to `struct` mode besides the starting token.
+
+## Examples
+
+Implement flags methods and traits for a custom flags type using `u8` as its underlying bits type:
+
+```
+# use bitflags::bitflags;
+struct Flags(u8);
+
+bitflags! {
+    impl Flags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+        const C = 0b0000_0100;
+    }
+}
+```
+
+# Named and unnamed flags
+
+Constants in the body of a declaration are flags. The identifier of the constant is the name of
+the flag. If the identifier is `_`, then the flag is unnamed. Unnamed flags don't appear in the
+generated API, but affect how bits are truncated.
+
+## Examples
+
+Adding an unnamed flag that makes all bits known:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+
+        const _ = !0;
+    }
+}
+```
+
+Flags types may define multiple unnamed flags:
+
+```
+# use bitflags::bitflags;
+bitflags! {
+    struct Flags: u8 {
+        const _ = 1;
+        const _ = 1 << 1;
+    }
+}
+```
+*/
+#[macro_export]
 macro_rules! bitflags {
     (
         $(#[$outer:meta])*
         $vis:vis struct $BitFlags:ident: $T:ty {
             $(
                 $(#[$inner:ident $($args:tt)*])*
-                const $Flag:ident = $value:expr;
+                const $Flag:tt = $value:expr;
             )*
         }
 
@@ -569,17 +458,17 @@
     ) => {
         // Declared in the scope of the `bitflags!` call
         // This type appears in the end-user's API
-        __declare_public_bitflags! {
+        $crate::__declare_public_bitflags! {
             $(#[$outer])*
             $vis struct $BitFlags
         }
 
         // Workaround for: https://github.com/bitflags/bitflags/issues/320
-        __impl_public_bitflags_consts! {
+        $crate::__impl_public_bitflags_consts! {
             $BitFlags: $T {
                 $(
                     $(#[$inner $($args)*])*
-                    $Flag = $value;
+                    const $Flag = $value;
                 )*
             }
         }
@@ -592,44 +481,51 @@
             unused_mut,
             unused_imports,
             non_upper_case_globals,
-            clippy::assign_op_pattern
+            clippy::assign_op_pattern,
+            clippy::indexing_slicing,
+            clippy::same_name_method,
+            clippy::iter_without_into_iter,
         )]
         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! {
+            $crate::__declare_internal_bitflags! {
                 $vis struct InternalBitFlags: $T
             }
 
-            __impl_internal_bitflags! {
+            $crate::__impl_internal_bitflags! {
                 InternalBitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
-                        $Flag = $value;
+                        const $Flag = $value;
                     )*
                 }
             }
 
             // This is where new library trait implementations can be added
-            __impl_external_bitflags! {
+            $crate::__impl_external_bitflags! {
                 InternalBitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
-                        $Flag;
+                        const $Flag;
                     )*
                 }
             }
 
-            __impl_public_bitflags_forward! {
+            $crate::__impl_public_bitflags_forward! {
                 $BitFlags: $T, InternalBitFlags
             }
 
-            __impl_public_bitflags_iter! {
+            $crate::__impl_public_bitflags_ops! {
+                $BitFlags
+            }
+
+            $crate::__impl_public_bitflags_iter! {
                 $BitFlags: $T, $BitFlags
             }
         };
 
-        bitflags! {
+        $crate::bitflags! {
             $($t)*
         }
     };
@@ -637,17 +533,17 @@
         impl $BitFlags:ident: $T:ty {
             $(
                 $(#[$inner:ident $($args:tt)*])*
-                const $Flag:ident = $value:expr;
+                const $Flag:tt = $value:expr;
             )*
         }
 
         $($t:tt)*
     ) => {
-        __impl_public_bitflags_consts! {
+        $crate::__impl_public_bitflags_consts! {
             $BitFlags: $T {
                 $(
                     $(#[$inner $($args)*])*
-                    $Flag = $value;
+                    const $Flag = $value;
                 )*
             }
         }
@@ -660,24 +556,29 @@
             unused_mut,
             unused_imports,
             non_upper_case_globals,
-            clippy::assign_op_pattern
+            clippy::assign_op_pattern,
+            clippy::iter_without_into_iter,
         )]
         const _: () = {
-            __impl_public_bitflags! {
+            $crate::__impl_public_bitflags! {
                 $BitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
-                        $Flag;
+                        const $Flag = $value;
                     )*
                 }
             }
 
-            __impl_public_bitflags_iter! {
+            $crate::__impl_public_bitflags_ops! {
+                $BitFlags
+            }
+
+            $crate::__impl_public_bitflags_iter! {
                 $BitFlags: $T, $BitFlags
             }
         };
 
-        bitflags! {
+        $crate::bitflags! {
             $($t)*
         }
     };
@@ -688,7 +589,7 @@
 ///
 /// 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)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_bitflags {
     (
@@ -715,80 +616,77 @@
             fn complement($complement0:ident) $complement:block
         }
     ) => {
-        #[allow(
-            dead_code,
-            deprecated,
-            unused_attributes
-        )]
+        #[allow(dead_code, deprecated, unused_attributes)]
         impl $PublicBitFlags {
-            /// Returns an empty set of flags.
+            /// Get a flags value with all bits unset.
             #[inline]
             pub const fn empty() -> Self {
                 $empty
             }
 
-            /// Returns the set containing all flags.
+            /// Get a flags value with all known bits set.
             #[inline]
             pub const fn all() -> Self {
                 $all
             }
 
-            /// Returns the raw value of the flags currently stored.
+            /// Get the underlying bits value.
+            ///
+            /// The returned value is exactly the bits set in this flags value.
             #[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.
+            /// Convert from a bits value.
+            ///
+            /// This method will return `None` if any unknown bits are set.
             #[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.
+            /// Convert from a bits value, unsetting any unknown bits.
             #[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).
+            /// Convert from a bits value exactly.
             #[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.
+            /// Get a flags value with the bits of a flag with the given name set.
             ///
-            /// Names are _case-sensitive_, so must correspond exactly to
-            /// the identifier given to the flag.
+            /// This method will return `None` if `name` is empty or doesn't
+            /// correspond to any named 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.
+            /// Whether all bits in this flags value are unset.
             #[inline]
             pub const fn is_empty(&self) -> bool {
                 let $is_empty0 = self;
                 $is_empty
             }
 
-            /// Returns `true` if all flags are currently set.
+            /// Whether all known bits in this flags value are 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`.
+            /// Whether any set bits in a source flags value are also set in a target flags value.
             #[inline]
             pub const fn intersects(&self, other: Self) -> bool {
                 let $intersects0 = self;
@@ -796,7 +694,7 @@
                 $intersects
             }
 
-            /// Returns `true` if all of the flags in `other` are contained within `self`.
+            /// Whether all set bits in a source flags value are also set in a target flags value.
             #[inline]
             pub const fn contains(&self, other: Self) -> bool {
                 let $contains0 = self;
@@ -804,7 +702,7 @@
                 $contains
             }
 
-            /// Inserts the specified flags in-place.
+            /// The bitwise or (`|`) of the bits in two flags values.
             #[inline]
             pub fn insert(&mut self, other: Self) {
                 let $insert0 = self;
@@ -812,7 +710,10 @@
                 $insert
             }
 
-            /// Removes the specified flags in-place.
+            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
+            ///
+            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
+            /// `remove` won't truncate `other`, but the `!` operator will.
             #[inline]
             pub fn remove(&mut self, other: Self) {
                 let $remove0 = self;
@@ -820,7 +721,7 @@
                 $remove
             }
 
-            /// Toggles the specified flags in-place.
+            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
             #[inline]
             pub fn toggle(&mut self, other: Self) {
                 let $toggle0 = self;
@@ -828,7 +729,7 @@
                 $toggle
             }
 
-            /// Inserts or removes the specified flags depending on the passed value.
+            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
             #[inline]
             pub fn set(&mut self, other: Self, value: bool) {
                 let $set0 = self;
@@ -837,16 +738,7 @@
                 $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
+            /// The bitwise and (`&`) of the bits in two flags values.
             #[inline]
             #[must_use]
             pub const fn intersection(self, other: Self) -> Self {
@@ -855,17 +747,7 @@
                 $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
+            /// The bitwise or (`|`) of the bits in two flags values.
             #[inline]
             #[must_use]
             pub const fn union(self, other: Self) -> Self {
@@ -874,18 +756,10 @@
                 $union
             }
 
-            /// Returns the difference between the flags in `self` and `other`.
+            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
             ///
-            /// 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
+            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
+            /// `difference` won't truncate `other`, but the `!` operator will.
             #[inline]
             #[must_use]
             pub const fn difference(self, other: Self) -> Self {
@@ -894,19 +768,7 @@
                 $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
+            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
             #[inline]
             #[must_use]
             pub const fn symmetric_difference(self, other: Self) -> Self {
@@ -915,19 +777,7 @@
                 $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
+            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
             #[inline]
             #[must_use]
             pub const fn complement(self) -> Self {
@@ -948,7 +798,7 @@
 ///
 /// 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)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __bitflags_expr_safe_attrs {
     // Entrypoint: Move all flags and all attributes into `unprocessed` lists
@@ -957,7 +807,7 @@
         $(#[$inner:ident $($args:tt)*])*
         { $e:expr }
     ) => {
-        __bitflags_expr_safe_attrs! {
+        $crate::__bitflags_expr_safe_attrs! {
             expr: { $e },
             attrs: {
                 // All attributes start here
@@ -982,7 +832,7 @@
             processed: [$($expr:tt)*],
         },
     ) => {
-        __bitflags_expr_safe_attrs! {
+        $crate::__bitflags_expr_safe_attrs! {
             expr: { $e },
             attrs: {
                 unprocessed: [
@@ -1009,7 +859,7 @@
             processed: [$($expr:tt)*],
         },
     ) => {
-        __bitflags_expr_safe_attrs! {
+        $crate::__bitflags_expr_safe_attrs! {
             expr: { $e },
                 attrs: {
                 unprocessed: [
@@ -1035,6 +885,30 @@
     }
 }
 
+/// Implement a flag, which may be a wildcard `_`.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __bitflags_flag {
+    (
+        {
+            name: _,
+            named: { $($named:tt)* },
+            unnamed: { $($unnamed:tt)* },
+        }
+    ) => {
+        $($unnamed)*
+    };
+    (
+        {
+            name: $Flag:ident,
+            named: { $($named:tt)* },
+            unnamed: { $($unnamed:tt)* },
+        }
+    ) => {
+        $($named)*
+    };
+}
+
 #[macro_use]
 mod public;
 #[macro_use]
@@ -1046,1105 +920,4 @@
 pub mod example_generated;
 
 #[cfg(test)]
-mod tests {
-    use std::{
-        collections::hash_map::DefaultHasher,
-        fmt,
-        hash::{Hash, Hasher},
-        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."]
-        #[doc = "> "]
-        #[doc = "> - Richard Feynman"]
-        #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        struct Flags: 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();
-        }
-
-        #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        struct _CfgFlags: u32 {
-            #[cfg(unix)]
-            const _CFG_A = 0b01;
-            #[cfg(windows)]
-            const _CFG_B = 0b01;
-            #[cfg(unix)]
-            const _CFG_C = Self::_CFG_A.bits() | 0b10;
-        }
-
-        #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        struct AnotherSetOfFlags: i8 {
-            const ANOTHER_FLAG = -1_i8;
-        }
-
-        #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        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! {
-        #[derive(Debug, PartialEq, Eq)]
-        struct FmtFlags: u16 {
-            const 고양이 = 0b0000_0001;
-            const 개 = 0b0000_0010;
-            const 물고기 = 0b0000_0100;
-            const 물고기_고양이 = Self::고양이.bits() | Self::물고기.bits();
-        }
-    }
-
-    impl str::FromStr for FmtFlags {
-        type Err = crate::parser::ParseError;
-
-        fn from_str(flags: &str) -> Result<Self, Self::Err> {
-            Ok(Self(flags.parse()?))
-        }
-    }
-
-    impl fmt::Display for FmtFlags {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            fmt::Display::fmt(&self.0, f)
-        }
-    }
-
-    bitflags! {
-        #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-        struct EmptyFlags: u32 {
-        }
-    }
-
-    #[test]
-    fn test_bits() {
-        assert_eq!(Flags::empty().bits(), 0b00000000);
-        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);
-
-        assert_eq!(EmptyFlags::empty().bits(), 0b00000000);
-    }
-
-    #[test]
-    fn test_from_bits() {
-        assert_eq!(Flags::from_bits(0), Some(Flags::empty()));
-        assert_eq!(Flags::from_bits(0b1), Some(Flags::A));
-        assert_eq!(Flags::from_bits(0b10), Some(Flags::B));
-        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)
-        );
-
-        assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty()));
-        assert_eq!(EmptyFlags::from_bits(0b1), None);
-    }
-
-    #[test]
-    fn test_from_bits_truncate() {
-        assert_eq!(Flags::from_bits_truncate(0), Flags::empty());
-        assert_eq!(Flags::from_bits_truncate(0b1), Flags::A);
-        assert_eq!(Flags::from_bits_truncate(0b10), Flags::B);
-        assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B));
-        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()
-        );
-
-        assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty());
-        assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty());
-    }
-
-    #[test]
-    fn test_from_bits_retain() {
-        let extra = Flags::from_bits_retain(0b1000);
-        assert_eq!(Flags::from_bits_retain(0), Flags::empty());
-        assert_eq!(Flags::from_bits_retain(0b1), Flags::A);
-        assert_eq!(Flags::from_bits_retain(0b10), Flags::B);
-
-        assert_eq!(Flags::from_bits_retain(0b11), (Flags::A | Flags::B));
-        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),
-            (extra | EmptyFlags::empty())
-        );
-    }
-
-    #[test]
-    fn test_is_empty() {
-        assert!(Flags::empty().is_empty());
-        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());
-        assert!(EmptyFlags::all().is_empty());
-    }
-
-    #[test]
-    fn test_is_all() {
-        assert!(Flags::all().is_all());
-        assert!(!Flags::A.is_all());
-        assert!(Flags::ABC.is_all());
-
-        let extra = Flags::from_bits_retain(0b1000);
-        assert!(!extra.is_all());
-        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());
-        assert!(EmptyFlags::empty().is_all());
-    }
-
-    #[test]
-    fn test_two_empties_do_not_intersect() {
-        let e1 = Flags::empty();
-        let e2 = Flags::empty();
-        assert!(!e1.intersects(e2));
-
-        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
-
-        assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG));
-    }
-
-    #[test]
-    fn test_empty_does_not_intersect_with_full() {
-        let e1 = Flags::empty();
-        let e2 = Flags::ABC;
-        assert!(!e1.intersects(e2));
-
-        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
-    }
-
-    #[test]
-    fn test_disjoint_intersects() {
-        let e1 = Flags::A;
-        let e2 = Flags::B;
-        assert!(!e1.intersects(e2));
-
-        assert!(!<Flags as crate::Flags>::intersects(&e1, e2));
-    }
-
-    #[test]
-    fn test_overlapping_intersects() {
-        let e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        assert!(e1.intersects(e2));
-
-        assert!(<Flags as crate::Flags>::intersects(&e1, e2));
-    }
-
-    #[test]
-    fn test_contains() {
-        let e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        assert!(!e1.contains(e2));
-        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()));
-    }
-
-    #[test]
-    fn test_insert() {
-        let mut e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        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);
-    }
-
-    #[test]
-    fn test_remove() {
-        let mut e1 = Flags::A | Flags::B;
-        let e2 = Flags::A | Flags::C;
-        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());
-    }
-
-    #[test]
-    fn test_operators() {
-        let e1 = Flags::A | Flags::C;
-        let e2 = Flags::B | Flags::C;
-        assert_eq!((e1 | e2), Flags::ABC); // union
-        assert_eq!((e1 & e2), Flags::C); // intersection
-        assert_eq!((e1 - e2), Flags::A); // set difference
-        assert_eq!(!e2, Flags::A); // set complement
-        assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle
-        let mut e3 = e1;
-        e3.toggle(e2);
-        assert_eq!(e3, Flags::A | Flags::B);
-
-        let mut m4 = AnotherSetOfFlags::empty();
-        m4.toggle(AnotherSetOfFlags::empty());
-        assert_eq!(m4, AnotherSetOfFlags::empty());
-    }
-
-    #[test]
-    fn test_operators_unchecked() {
-        let extra = Flags::from_bits_retain(0b1000);
-        let e1 = Flags::A | Flags::C | extra;
-        let e2 = Flags::B | Flags::C;
-        assert_eq!((e1 | e2), (Flags::ABC | extra)); // union
-        assert_eq!((e1 & e2), Flags::C); // intersection
-        assert_eq!((e1 - e2), (Flags::A | extra)); // set difference
-        assert_eq!(!e2, Flags::A); // set complement
-        assert_eq!(!e1, Flags::B); // set complement
-        assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle
-        let mut e3 = e1;
-        e3.toggle(e2);
-        assert_eq!(e3, Flags::A | Flags::B | extra);
-    }
-
-    #[test]
-    fn test_set_ops_basic() {
-        let ab = Flags::A.union(Flags::B);
-        let ac = Flags::A.union(Flags::C);
-        let bc = Flags::B.union(Flags::C);
-        assert_eq!(ab.bits(), 0b011);
-        assert_eq!(bc.bits(), 0b110);
-        assert_eq!(ac.bits(), 0b101);
-
-        assert_eq!(ab, Flags::B.union(Flags::A));
-        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);
-
-        assert_eq!(ac, Flags::A | Flags::C);
-        assert_eq!(bc, Flags::B | Flags::C);
-
-        assert_eq!(ac.union(bc), ac | bc);
-        assert_eq!(ac.union(bc), Flags::ABC);
-        assert_eq!(bc.union(ac), Flags::ABC);
-
-        assert_eq!(ac.intersection(bc), ac & bc);
-        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]
-    fn test_set_ops_const() {
-        // These just test that these compile and don't cause use-site panics
-        // (would be possible if we had some sort of UB)
-        const INTERSECT: Flags = Flags::all().intersection(Flags::C);
-        const UNION: Flags = Flags::A.union(Flags::C);
-        const DIFFERENCE: Flags = Flags::all().difference(Flags::A);
-        const COMPLEMENT: Flags = Flags::C.complement();
-        const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE);
-        assert_eq!(INTERSECT, Flags::C);
-        assert_eq!(UNION, Flags::A | Flags::C);
-        assert_eq!(DIFFERENCE, Flags::all() - Flags::A);
-        assert_eq!(COMPLEMENT, !Flags::C);
-        assert_eq!(
-            SYM_DIFFERENCE,
-            (Flags::A | Flags::C) ^ (Flags::all() - Flags::A)
-        );
-    }
-
-    #[test]
-    fn test_set_ops_unchecked() {
-        let extra = Flags::from_bits_retain(0b1000);
-        let e1 = Flags::A.union(Flags::C).union(extra);
-        let e2 = Flags::B.union(Flags::C);
-        assert_eq!(e1.bits(), 0b1101);
-        assert_eq!(e1.union(e2), (Flags::ABC | extra));
-        assert_eq!(e1.intersection(e2), Flags::C);
-        assert_eq!(e1.difference(e2), Flags::A | extra);
-        assert_eq!(e2.difference(e1), Flags::B);
-        assert_eq!(e2.complement(), Flags::A);
-        assert_eq!(e1.complement(), Flags::B);
-        assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle
-    }
-
-    #[test]
-    fn test_set_ops_exhaustive() {
-        // Define a flag that contains gaps to help exercise edge-cases,
-        // especially around "unknown" flags (e.g. ones outside of `all()`
-        // `from_bits_retain`).
-        // - when lhs and rhs both have different sets of unknown flags.
-        // - unknown flags at both ends, and in the middle
-        // - cases with "gaps".
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Test: u16 {
-                // Intentionally no `A`
-                const B = 0b000000010;
-                // Intentionally no `C`
-                const D = 0b000001000;
-                const E = 0b000010000;
-                const F = 0b000100000;
-                const G = 0b001000000;
-                // Intentionally no `H`
-                const I = 0b100000000;
-            }
-        }
-        let iter_test_flags = || (0..=0b111_1111_1111).map(|bits| Test::from_bits_retain(bits));
-
-        for a in iter_test_flags() {
-            assert_eq!(
-                a.complement(),
-                Test::from_bits_truncate(!a.bits()),
-                "wrong result: !({:?})",
-                a,
-            );
-            assert_eq!(a.complement(), !a, "named != op: !({:?})", a);
-            for b in iter_test_flags() {
-                // Check that the named operations produce the expected bitwise
-                // values.
-                assert_eq!(
-                    a.union(b).bits(),
-                    a.bits() | b.bits(),
-                    "wrong result: `{:?}` | `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(
-                    a.intersection(b).bits(),
-                    a.bits() & b.bits(),
-                    "wrong result: `{:?}` & `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(
-                    a.symmetric_difference(b).bits(),
-                    a.bits() ^ b.bits(),
-                    "wrong result: `{:?}` ^ `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(
-                    a.difference(b).bits(),
-                    a.bits() & !b.bits(),
-                    "wrong result: `{:?}` - `{:?}`",
-                    a,
-                    b,
-                );
-                // Note: Difference is checked as both `a - b` and `b - a`
-                assert_eq!(
-                    b.difference(a).bits(),
-                    b.bits() & !a.bits(),
-                    "wrong result: `{:?}` - `{:?}`",
-                    b,
-                    a,
-                );
-                // Check that the named set operations are equivalent to the
-                // bitwise equivalents
-                assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,);
-                assert_eq!(
-                    a.intersection(b),
-                    a & b,
-                    "named != op: `{:?}` & `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(
-                    a.symmetric_difference(b),
-                    a ^ b,
-                    "named != op: `{:?}` ^ `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,);
-                // Note: Difference is checked as both `a - b` and `b - a`
-                assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,);
-                // Verify that the operations which should be symmetric are
-                // actually symmetric.
-                assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,);
-                assert_eq!(
-                    a.intersection(b),
-                    b.intersection(a),
-                    "asymmetry: `{:?}` & `{:?}`",
-                    a,
-                    b,
-                );
-                assert_eq!(
-                    a.symmetric_difference(b),
-                    b.symmetric_difference(a),
-                    "asymmetry: `{:?}` ^ `{:?}`",
-                    a,
-                    b,
-                );
-            }
-        }
-    }
-
-    #[test]
-    fn test_set() {
-        let mut e1 = Flags::A | Flags::C;
-        e1.set(Flags::B, true);
-        e1.set(Flags::C, false);
-
-        assert_eq!(e1, Flags::A | Flags::B);
-    }
-
-    #[test]
-    fn test_assignment_operators() {
-        let mut m1 = Flags::empty();
-        let e1 = Flags::A | Flags::C;
-        // union
-        m1 |= Flags::A;
-        assert_eq!(m1, Flags::A);
-        // intersection
-        m1 &= e1;
-        assert_eq!(m1, Flags::A);
-        // set difference
-        m1 -= m1;
-        assert_eq!(m1, Flags::empty());
-        // toggle
-        m1 ^= e1;
-        assert_eq!(m1, e1);
-    }
-
-    #[test]
-    fn test_const_fn() {
-        const _M1: Flags = Flags::empty();
-
-        const M2: Flags = Flags::A;
-        assert_eq!(M2, Flags::A);
-
-        const M3: Flags = Flags::C;
-        assert_eq!(M3, Flags::C);
-    }
-
-    #[test]
-    fn test_extend() {
-        let mut flags;
-
-        flags = Flags::empty();
-        flags.extend([].iter().cloned());
-        assert_eq!(flags, Flags::empty());
-
-        flags = Flags::empty();
-        flags.extend([Flags::A, Flags::B].iter().cloned());
-        assert_eq!(flags, Flags::A | Flags::B);
-
-        flags = Flags::A;
-        flags.extend([Flags::A, Flags::B].iter().cloned());
-        assert_eq!(flags, Flags::A | Flags::B);
-
-        flags = Flags::B;
-        flags.extend([Flags::A, Flags::ABC].iter().cloned());
-        assert_eq!(flags, Flags::ABC);
-    }
-
-    #[test]
-    fn test_from_iterator() {
-        assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty());
-        assert_eq!(
-            [Flags::A, Flags::B].iter().cloned().collect::<Flags>(),
-            Flags::A | Flags::B
-        );
-        assert_eq!(
-            [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(),
-            Flags::ABC
-        );
-    }
-
-    #[test]
-    fn test_lt() {
-        let mut a = Flags::empty();
-        let mut b = Flags::empty();
-
-        assert!(!(a < b) && !(b < a));
-        b = Flags::B;
-        assert!(a < b);
-        a = Flags::C;
-        assert!(!(a < b) && b < a);
-        b = Flags::C | Flags::B;
-        assert!(a < b);
-    }
-
-    #[test]
-    fn test_ord() {
-        let mut a = Flags::empty();
-        let mut b = Flags::empty();
-
-        assert!(a <= b && a >= b);
-        a = Flags::A;
-        assert!(a > b && a >= b);
-        assert!(b < a && b <= a);
-        b = Flags::B;
-        assert!(b > a && b >= a);
-        assert!(a < b && a <= b);
-    }
-
-    fn hash<T: Hash>(t: &T) -> u64 {
-        let mut s = DefaultHasher::new();
-        t.hash(&mut s);
-        s.finish()
-    }
-
-    #[test]
-    fn test_hash() {
-        let mut x = Flags::empty();
-        let mut y = Flags::empty();
-        assert_eq!(hash(&x), hash(&y));
-        x = Flags::all();
-        y = Flags::ABC;
-        assert_eq!(hash(&x), hash(&y));
-    }
-
-    #[test]
-    fn test_default() {
-        assert_eq!(Flags::empty(), Flags::default());
-    }
-
-    #[test]
-    fn test_debug() {
-        assert_eq!(format!("{:?}", Flags::A | Flags::B), "Flags(A | B)");
-        assert_eq!(format!("{:?}", Flags::empty()), "Flags(0x0)");
-        assert_eq!(format!("{:?}", Flags::ABC), "Flags(A | B | C)");
-
-        let extra = Flags::from_bits_retain(0xb8);
-
-        assert_eq!(format!("{:?}", extra), "Flags(0xb8)");
-        assert_eq!(format!("{:?}", Flags::A | extra), "Flags(A | 0xb8)");
-
-        assert_eq!(
-            format!("{:?}", Flags::ABC | extra),
-            "Flags(A | B | C | ABC | 0xb8)"
-        );
-
-        assert_eq!(format!("{:?}", EmptyFlags::empty()), "EmptyFlags(0x0)");
-    }
-
-    #[test]
-    fn test_display_from_str_roundtrip() {
-        fn format_parse_case<T: fmt::Debug + fmt::Display + str::FromStr + PartialEq>(flags: T) where <T as str::FromStr>::Err: fmt::Display {
-            assert_eq!(flags, {
-                match flags.to_string().parse::<T>() {
-                    Ok(flags) => flags,
-                    Err(e) => panic!("failed to parse `{}`: {}", flags, e),
-                }
-            });
-        }
-
-        fn parse_case<T: fmt::Debug + str::FromStr + PartialEq>(expected: T, flags: &str) where <T as str::FromStr>::Err: fmt::Display + fmt::Debug {
-            assert_eq!(expected, flags.parse::<T>().unwrap());
-        }
-
-        bitflags! {
-            #[derive(Debug, Eq, PartialEq)]
-            pub struct MultiBitFmtFlags: u8 {
-                const A = 0b0000_0001u8;
-                const B = 0b0001_1110u8;
-            }
-        }
-
-        impl fmt::Display for MultiBitFmtFlags {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                fmt::Display::fmt(&self.0, f)
-            }
-        }
-
-        impl str::FromStr for MultiBitFmtFlags {
-            type Err = crate::parser::ParseError;
-
-            fn from_str(s: &str) -> Result<Self, Self::Err> {
-                Ok(MultiBitFmtFlags(s.parse()?))
-            }
-        }
-
-        format_parse_case(FmtFlags::empty());
-        format_parse_case(FmtFlags::all());
-        format_parse_case(FmtFlags::고양이);
-        format_parse_case(FmtFlags::고양이 | FmtFlags::개);
-        format_parse_case(FmtFlags::물고기_고양이);
-        format_parse_case(FmtFlags::from_bits_retain(0xb8));
-        format_parse_case(FmtFlags::from_bits_retain(0x20));
-        format_parse_case(MultiBitFmtFlags::from_bits_retain(3));
-
-        parse_case(FmtFlags::empty(), "");
-        parse_case(FmtFlags::empty(), " \r\n\t");
-        parse_case(FmtFlags::empty(), "0x0");
-
-        parse_case(FmtFlags::고양이, "고양이");
-        parse_case(FmtFlags::고양이, "  고양이  ");
-        parse_case(FmtFlags::고양이, "고양이 | 고양이 | 고양이");
-        parse_case(FmtFlags::고양이, "0x01");
-
-        parse_case(FmtFlags::고양이 | FmtFlags::개, "고양이 | 개");
-        parse_case(FmtFlags::고양이 | FmtFlags::개, "고양이|개");
-        parse_case(FmtFlags::고양이 | FmtFlags::개, "\n고양이|개 ");
-
-        parse_case(FmtFlags::고양이 | FmtFlags::물고기, "물고기_고양이");
-    }
-
-    #[test]
-    fn test_from_str_err() {
-        fn parse_case(pat: &str, flags: &str) {
-            let err = flags.parse::<FmtFlags>().unwrap_err().to_string();
-            assert!(err.contains(pat), "`{}` not found in error `{}`", pat, err);
-        }
-
-        parse_case("empty flag", "|");
-        parse_case("empty flag", "|||");
-        parse_case("empty flag", "고양이 |");
-        parse_case("unrecognized named flag", "NOT_A_FLAG");
-        parse_case("unrecognized named flag", "고양이 개");
-        parse_case("unrecognized named flag", "고양이 | NOT_A_FLAG");
-        parse_case("invalid hex flag", "0xhi");
-        parse_case("invalid hex flag", "고양이 | 0xhi");
-    }
-
-    #[test]
-    fn test_binary() {
-        assert_eq!(format!("{:b}", Flags::ABC), "111");
-        assert_eq!(format!("{:#b}", Flags::ABC), "0b111");
-        let extra = Flags::from_bits_retain(0b1010000);
-        assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111");
-        assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111");
-    }
-
-    #[test]
-    fn test_octal() {
-        assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777");
-        assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777");
-        let extra = LongFlags::from_bits_retain(0o5000000);
-        assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777");
-        assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777");
-    }
-
-    #[test]
-    fn test_lowerhex() {
-        assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff");
-        assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff");
-        let extra = LongFlags::from_bits_retain(0xe00000);
-        assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff");
-        assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff");
-    }
-
-    #[test]
-    fn test_upperhex() {
-        assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF");
-        assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF");
-        let extra = LongFlags::from_bits_retain(0xe00000);
-        assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF");
-        assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF");
-    }
-
-    mod submodule {
-        bitflags! {
-            #[derive(Clone, Copy)]
-            pub struct PublicFlags: i8 {
-                const X = 0;
-            }
-
-            #[derive(Clone, Copy)]
-            struct PrivateFlags: i8 {
-                const Y = 0;
-            }
-        }
-
-        #[test]
-        fn test_private() {
-            let _ = PrivateFlags::Y;
-        }
-    }
-
-    #[test]
-    fn test_public() {
-        let _ = submodule::PublicFlags::X;
-    }
-
-    mod t1 {
-        mod foo {
-            pub type Bar = i32;
-        }
-
-        bitflags! {
-            /// baz
-            #[derive(Clone, Copy)]
-            struct Flags: foo::Bar {
-                const A = 0b00000001;
-                #[cfg(foo)]
-                const B = 0b00000010;
-                #[cfg(foo)]
-                const C = 0b00000010;
-            }
-        }
-    }
-
-    #[test]
-    fn test_in_function() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u8 {
-                const A = 1;
-                #[cfg(any())] // false
-                const B = 2;
-            }
-        }
-        assert_eq!(Flags::all(), Flags::A);
-        assert_eq!(format!("{:?}", Flags::A), "Flags(A)");
-    }
-
-    #[test]
-    fn test_deprecated() {
-        bitflags! {
-            #[derive(Clone, Copy)]
-            pub struct TestFlags: u32 {
-                #[deprecated(note = "Use something else.")]
-                const ONE = 1;
-            }
-        }
-    }
-
-    #[test]
-    fn test_pub_crate() {
-        mod module {
-            bitflags! {
-                #[derive(Clone, Copy)]
-                pub (crate) struct Test: u8 {
-                    const FOO = 1;
-                }
-            }
-        }
-
-        assert_eq!(module::Test::FOO.bits(), 1);
-    }
-
-    #[test]
-    fn test_pub_in_module() {
-        mod module {
-            mod submodule {
-                bitflags! {
-                    // `pub (in super)` means only the module `module` will
-                    // be able to access this.
-                    #[derive(Clone, Copy)]
-                    pub (in super) struct Test: u8 {
-                        const FOO = 1;
-                    }
-                }
-            }
-
-            mod test {
-                // Note: due to `pub (in super)`,
-                // this cannot be accessed directly by the testing code.
-                pub(super) fn value() -> u8 {
-                    super::submodule::Test::FOO.bits()
-                }
-            }
-
-            pub fn value() -> u8 {
-                test::value()
-            }
-        }
-
-        assert_eq!(module::value(), 1)
-    }
-
-    #[test]
-    fn test_zero_value_flags() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u32 {
-                const NONE = 0b0;
-                const SOME = 0b1;
-            }
-        }
-
-        assert!(Flags::empty().contains(Flags::NONE));
-        assert!(Flags::SOME.contains(Flags::NONE));
-        assert!(Flags::NONE.is_empty());
-
-        assert_eq!(format!("{:?}", Flags::SOME), "Flags(NONE | SOME)");
-    }
-
-    #[test]
-    fn test_empty_bitflags() {
-        bitflags! {}
-    }
-
-    #[test]
-    fn test_u128_bitflags() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u128 {
-                const A = 0x0000_0000_0000_0000_0000_0000_0000_0001;
-                const B = 0x0000_0000_0000_1000_0000_0000_0000_0000;
-                const C = 0x8000_0000_0000_0000_0000_0000_0000_0000;
-                const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
-            }
-        }
-
-        assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C);
-        assert_eq!(Flags::A.bits(), 0x0000_0000_0000_0000_0000_0000_0000_0001);
-        assert_eq!(Flags::B.bits(), 0x0000_0000_0000_1000_0000_0000_0000_0000);
-        assert_eq!(Flags::C.bits(), 0x8000_0000_0000_0000_0000_0000_0000_0000);
-        assert_eq!(Flags::ABC.bits(), 0x8000_0000_0000_1000_0000_0000_0000_0001);
-        assert_eq!(format!("{:?}", Flags::A), "Flags(A)");
-        assert_eq!(format!("{:?}", Flags::B), "Flags(B)");
-        assert_eq!(format!("{:?}", Flags::C), "Flags(C)");
-        assert_eq!(format!("{:?}", Flags::ABC), "Flags(A | B | C)");
-    }
-
-    #[test]
-    fn test_from_bits_edge_cases() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u8 {
-                const A = 0b00000001;
-                const BC = 0b00000110;
-            }
-        }
-
-        let flags = Flags::from_bits(0b00000100);
-        assert_eq!(flags, None);
-        let flags = Flags::from_bits(0b00000101);
-        assert_eq!(flags, None);
-    }
-
-    #[test]
-    fn test_from_bits_truncate_edge_cases() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u8 {
-                const A = 0b00000001;
-                const BC = 0b00000110;
-            }
-        }
-
-        let flags = Flags::from_bits_truncate(0b00000100);
-        assert_eq!(flags, Flags::empty());
-        let flags = Flags::from_bits_truncate(0b00000101);
-        assert_eq!(flags, Flags::A);
-    }
-
-    #[test]
-    fn test_iter() {
-        bitflags! {
-            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-            struct Flags: u32 {
-                const ONE  = 0b001;
-                const TWO  = 0b010;
-                const THREE = 0b100;
-                #[cfg(windows)]
-                const FOUR_WIN = 0b1000;
-                #[cfg(unix)]
-                const FOUR_UNIX = 0b10000;
-                const FIVE = 0b01000100;
-            }
-        }
-
-        let count = {
-            #[cfg(any(unix, windows))]
-            {
-                5
-            }
-
-            #[cfg(not(any(unix, windows)))]
-            {
-                4
-            }
-        };
-
-        let flags = Flags::all();
-        assert_eq!(flags.into_iter().count(), count);
-
-        for flag in flags.into_iter() {
-            assert!(flags.contains(flag));
-        }
-
-        let mut iter = flags.iter_names();
-
-        assert_eq!(iter.next().unwrap(), ("ONE", Flags::ONE));
-        assert_eq!(iter.next().unwrap(), ("TWO", Flags::TWO));
-        assert_eq!(iter.next().unwrap(), ("THREE", Flags::THREE));
-
-        #[cfg(unix)]
-        {
-            assert_eq!(iter.next().unwrap(), ("FOUR_UNIX", Flags::FOUR_UNIX));
-        }
-        #[cfg(windows)]
-        {
-            assert_eq!(iter.next().unwrap(), ("FOUR_WIN", Flags::FOUR_WIN));
-        }
-
-        assert_eq!(iter.next().unwrap(), ("FIVE", Flags::FIVE));
-
-        assert_eq!(iter.next(), None);
-
-        let flags = Flags::empty();
-        assert_eq!(flags.into_iter().count(), 0);
-
-        let flags = Flags::ONE | Flags::THREE;
-        assert_eq!(flags.into_iter().count(), 2);
-
-        let mut iter = flags.iter_names();
-
-        assert_eq!(iter.next().unwrap(), ("ONE", Flags::ONE));
-        assert_eq!(iter.next().unwrap(), ("THREE", Flags::THREE));
-        assert_eq!(iter.next(), None);
-
-        let flags = Flags::from_bits_retain(0b1000_0000);
-        assert_eq!(flags.into_iter().count(), 1);
-        assert_eq!(flags.iter_names().count(), 0);
-    }
-
-    #[test]
-    fn into_iter_from_iter_roundtrip() {
-        let flags = Flags::ABC | Flags::from_bits_retain(0b1000_0000);
-
-        assert_eq!(flags, flags.into_iter().collect::<Flags>());
-    }
-
-    #[test]
-    fn test_from_name() {
-        let flags = Flags::all();
-
-        let mut rebuilt = Flags::empty();
-
-        for (name, value) in flags.iter_names() {
-            assert_eq!(value, Flags::from_name(name).unwrap());
-
-            rebuilt |= Flags::from_name(name).unwrap();
-        }
-
-        assert_eq!(flags, rebuilt);
-    }
-
-    #[test]
-    fn bits_types() {
-        bitflags! {
-            pub struct I8: i8 {
-                const A = 1;
-            }
-
-            pub struct I16: i16 {
-                const A = 1;
-            }
-
-            pub struct I32: i32 {
-                const A = 1;
-            }
-
-            pub struct I64: i64 {
-                const A = 1;
-            }
-
-            pub struct I128: i128 {
-                const A = 1;
-            }
-
-            pub struct Isize: isize {
-                const A = 1;
-            }
-
-            pub struct U8: u8 {
-                const A = 1;
-            }
-
-            pub struct U16: u16 {
-                const A = 1;
-            }
-
-            pub struct U32: u32 {
-                const A = 1;
-            }
-
-            pub struct U64: u64 {
-                const A = 1;
-            }
-
-            pub struct U128: u128 {
-                const A = 1;
-            }
-
-            pub struct Usize: usize {
-                const A = 1;
-            }
-        }
-    }
-}
+mod tests;
diff --git a/src/parser.rs b/src/parser.rs
index aac9042..130dc2e 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,41 +1,44 @@
-//! Parsing flags from text.
-//!
-//! `bitflags` defines the following *whitespace-insensitive*, *case-sensitive* grammar for flags formatted
-//! as text:
-//!
-//! - _Flags:_ (_Flag_)`|`*
-//! - _Flag:_ _Identifier_ | _HexNumber_
-//! - _Identifier:_ Any Rust identifier
-//! - _HexNumber_: `0x`([0-9a-fA-F])*
-//!
-//! As an example, this is how `Flags::A | Flags::B | 0x0c` can be represented as text:
-//!
-//! ```text
-//! A | B | 0x0c
-//! ```
-//!
-//! Alternatively, it could be represented without whitespace:
-//!
-//! ```text
-//! A|B|0x0C
-//! ```
-//!
-//! Note that identifiers are *case-sensitive*, so the following is *not equivalent*:
-//!
-//! ```text
-//! a | b | 0x0c
-//! ```
+/*!
+Parsing flags from text.
+
+Format and parse a flags value as text using the following grammar:
+
+- _Flags:_ (_Whitespace_ _Flag_ _Whitespace_)`|`*
+- _Flag:_ _Name_ | _Hex Number_
+- _Name:_ The name of any defined flag
+- _Hex Number_: `0x`([0-9a-fA-F])*
+- _Whitespace_: (\s)*
+
+As an example, this is how `Flags::A | Flags::B | 0x0c` can be represented as text:
+
+```text
+A | B | 0x0c
+```
+
+Alternatively, it could be represented without whitespace:
+
+```text
+A|B|0x0C
+```
+
+Note that identifiers are *case-sensitive*, so the following is *not equivalent*:
+
+```text
+a|b|0x0C
+```
+*/
 
 #![allow(clippy::let_unit_value)]
 
 use core::fmt::{self, Write};
 
-use crate::{Flags, Bits};
+use crate::{Bits, Flags};
 
-/// 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.
+/**
+Write a flags value as text.
+
+Any bits that aren't part of a contained 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,
@@ -48,7 +51,7 @@
     // followed by a hex number of any remaining bits that are set
     // but don't correspond to any flags.
 
-    // Iterate over the valid flags
+    // Iterate over known flag values
     let mut first = true;
     let mut iter = flags.iter_names();
     for (name, _) in &mut iter {
@@ -85,9 +88,12 @@
     }
 }
 
-/// Parse a set of flags from text.
-///
-/// This function will fail on unknown flags rather than ignore them.
+/**
+Parse a flags value from text.
+
+This function will fail on any names that don't correspond to defined flags.
+Unknown bits will be retained.
+*/
 pub fn from_str<B: Flags>(input: &str) -> Result<B, ParseError>
 where
     B::Bits: ParseHex,
@@ -110,7 +116,8 @@
         // 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))?;
+            let bits =
+                <B::Bits>::parse_hex(flag).map_err(|_| ParseError::invalid_hex_flag(flag))?;
 
             B::from_bits_retain(bits)
         }
@@ -127,13 +134,19 @@
     Ok(parsed_flags)
 }
 
-/// Encode a value as a hex number.
+/**
+Encode a value as a hex string.
+
+Implementors of this trait should not write the `0x` prefix.
+*/
 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.
+/**
+Parse a value from a hex string.
+*/
 pub trait ParseHex {
     /// Parse the value from hex.
     fn parse_hex(input: &str) -> Result<Self, ParseError>
diff --git a/src/public.rs b/src/public.rs
index 57ab0ea..dc2d726 100644
--- a/src/public.rs
+++ b/src/public.rs
@@ -6,7 +6,7 @@
 /// Declare the user-facing bitflags struct.
 ///
 /// This type is guaranteed to be a newtype with a `bitflags`-facing type as its single field.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __declare_public_bitflags {
     (
@@ -22,13 +22,13 @@
 ///
 /// 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)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_forward {
     (
         $PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident
     ) => {
-        __impl_bitflags! {
+        $crate::__impl_bitflags! {
             $PublicBitFlags: $T {
                 fn empty() {
                     Self($InternalBitFlags::empty())
@@ -117,8 +117,6 @@
                 }
             }
         }
-
-        __impl_public_bitflags_ops!($PublicBitFlags);
     };
 }
 
@@ -126,25 +124,41 @@
 ///
 /// 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)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags {
     (
         $BitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt = $value:expr;
             )*
         }
     ) => {
-        __impl_bitflags! {
+        $crate::__impl_bitflags! {
             $BitFlags: $T {
                 fn empty() {
                     Self(<$T as $crate::Bits>::EMPTY)
                 }
 
                 fn all() {
-                    Self::from_bits_truncate(<$T as $crate::Bits>::ALL)
+                    let mut truncated = <$T as $crate::Bits>::EMPTY;
+                    let mut i = 0;
+
+                    $(
+                        $crate::__bitflags_expr_safe_attrs!(
+                            $(#[$inner $($args)*])*
+                            {{
+                                let flag = <$PublicBitFlags as $crate::Flags>::FLAGS[i].value().bits();
+
+                                truncated = truncated | flag;
+                                i += 1;
+                            }}
+                        );
+                    )*
+
+                    let _ = i;
+                    Self::from_bits_retain(truncated)
                 }
 
                 fn bits(f) {
@@ -162,24 +176,7 @@
                 }
 
                 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)
+                    Self(bits & Self::all().bits())
                 }
 
                 fn from_bits_retain(bits) {
@@ -188,14 +185,20 @@
 
                 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()));
-                                }
-                            }
-                        );
+                        $crate::__bitflags_flag!({
+                            name: $Flag,
+                            named: {
+                                $crate::__bitflags_expr_safe_attrs!(
+                                    $(#[$inner $($args)*])*
+                                    {
+                                        if name == $crate::__private::core::stringify!($Flag) {
+                                            return $crate::__private::core::option::Option::Some(Self($PublicBitFlags::$Flag.bits()));
+                                        }
+                                    }
+                                );
+                            },
+                            unnamed: {},
+                        });
                     )*
 
                     let _ = name;
@@ -203,31 +206,33 @@
                 }
 
                 fn is_empty(f) {
-                    f.0 == Self::empty().0
+                    f.bits() == <$T as $crate::Bits>::EMPTY
                 }
 
                 fn is_all(f) {
-                    Self::all().0 | f.0 == f.0
+                    // 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() | f.bits() == f.bits()
                 }
 
                 fn intersects(f, other) {
-                    !(Self(f.0 & other.0)).is_empty()
+                    f.bits() & other.bits() != <$T as $crate::Bits>::EMPTY
                 }
 
                 fn contains(f, other) {
-                    (f.0 & other.0) == other.0
+                    f.bits() & other.bits() == other.bits()
                 }
 
                 fn insert(f, other) {
-                    f.0 = f.0 | other.0;
+                    *f = Self::from_bits_retain(f.bits()).union(other);
                 }
 
                 fn remove(f, other) {
-                    f.0 = f.0 & !other.0;
+                    *f = Self::from_bits_retain(f.bits()).difference(other);
                 }
 
                 fn toggle(f, other) {
-                    f.0 = f.0 ^ other.0;
+                    *f = Self::from_bits_retain(f.bits()).symmetric_difference(other);
                 }
 
                 fn set(f, other, value) {
@@ -239,47 +244,59 @@
                 }
 
                 fn intersection(f, other) {
-                    Self(f.0 & other.0)
+                    Self::from_bits_retain(f.bits() & other.bits())
                 }
 
                 fn union(f, other) {
-                    Self(f.0 | other.0)
+                    Self::from_bits_retain(f.bits() | other.bits())
                 }
 
                 fn difference(f, other) {
-                    Self(f.0 & !other.0)
+                    Self::from_bits_retain(f.bits() & !other.bits())
                 }
 
                 fn symmetric_difference(f, other) {
-                    Self(f.0 ^ other.0)
+                    Self::from_bits_retain(f.bits() ^ other.bits())
                 }
 
                 fn complement(f) {
-                    Self::from_bits_truncate(!f.0)
+                    Self::from_bits_truncate(!f.bits())
                 }
             }
         }
-
-        __impl_public_bitflags_ops!($BitFlags);
     };
 }
 
 /// Implement iterators on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_iter {
     ($BitFlags:ident: $T:ty, $PublicBitFlags:ident) => {
         impl $BitFlags {
-            /// Iterate over enabled flag values.
+            /// Yield a set of contained flags values.
+            ///
+            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
+            /// will be yielded together as a final flags value.
             #[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()))
+                $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.
+            /// Yield a set of contained named flags values.
+            ///
+            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
+            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
             #[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()))
+                $crate::iter::IterNames::__private_const_new(
+                    <$PublicBitFlags as $crate::Flags>::FLAGS,
+                    $PublicBitFlags::from_bits_retain(self.bits()),
+                    $PublicBitFlags::from_bits_retain(self.bits()),
+                )
             }
         }
 
@@ -295,38 +312,54 @@
 }
 
 /// Implement traits on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[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)
+            fn fmt(
+                &self,
+                f: &mut $crate::__private::core::fmt::Formatter,
+            ) -> $crate::__private::core::fmt::Result {
+                let inner = self.0;
+                $crate::__private::core::fmt::Binary::fmt(&inner, f)
             }
         }
 
         impl $crate::__private::core::fmt::Octal for $PublicBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::Octal::fmt(&self.0, f)
+            fn fmt(
+                &self,
+                f: &mut $crate::__private::core::fmt::Formatter,
+            ) -> $crate::__private::core::fmt::Result {
+                let inner = self.0;
+                $crate::__private::core::fmt::Octal::fmt(&inner, f)
             }
         }
 
         impl $crate::__private::core::fmt::LowerHex for $PublicBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::LowerHex::fmt(&self.0, f)
+            fn fmt(
+                &self,
+                f: &mut $crate::__private::core::fmt::Formatter,
+            ) -> $crate::__private::core::fmt::Result {
+                let inner = self.0;
+                $crate::__private::core::fmt::LowerHex::fmt(&inner, f)
             }
         }
 
         impl $crate::__private::core::fmt::UpperHex for $PublicBitFlags {
-            fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result {
-                $crate::__private::core::fmt::UpperHex::fmt(&self.0, f)
+            fn fmt(
+                &self,
+                f: &mut $crate::__private::core::fmt::Formatter,
+            ) -> $crate::__private::core::fmt::Result {
+                let inner = self.0;
+                $crate::__private::core::fmt::UpperHex::fmt(&inner, f)
             }
         }
 
         impl $crate::__private::core::ops::BitOr for $PublicBitFlags {
             type Output = Self;
 
-            /// Returns the union of the two sets of flags.
+            /// The bitwise or (`|`) of the bits in two flags values.
             #[inline]
             fn bitor(self, other: $PublicBitFlags) -> Self {
                 self.union(other)
@@ -334,17 +367,17 @@
         }
 
         impl $crate::__private::core::ops::BitOrAssign for $PublicBitFlags {
-            /// Adds the set of flags.
+            /// The bitwise or (`|`) of the bits in two flags values.
             #[inline]
             fn bitor_assign(&mut self, other: Self) {
-                self.0 = self.0 | other.0;
+                self.insert(other);
             }
         }
 
         impl $crate::__private::core::ops::BitXor for $PublicBitFlags {
             type Output = Self;
 
-            /// Returns the left flags, but with all the right flags toggled.
+            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
             #[inline]
             fn bitxor(self, other: Self) -> Self {
                 self.symmetric_difference(other)
@@ -352,17 +385,17 @@
         }
 
         impl $crate::__private::core::ops::BitXorAssign for $PublicBitFlags {
-            /// Toggles the set of flags.
+            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
             #[inline]
             fn bitxor_assign(&mut self, other: Self) {
-                self.0 = self.0 ^ other.0
+                self.toggle(other);
             }
         }
 
         impl $crate::__private::core::ops::BitAnd for $PublicBitFlags {
             type Output = Self;
 
-            /// Returns the intersection between the two sets of flags.
+            /// The bitwise and (`&`) of the bits in two flags values.
             #[inline]
             fn bitand(self, other: Self) -> Self {
                 self.intersection(other)
@@ -370,17 +403,20 @@
         }
 
         impl $crate::__private::core::ops::BitAndAssign for $PublicBitFlags {
-            /// Disables all flags disabled in the set.
+            /// The bitwise and (`&`) of the bits in two flags values.
             #[inline]
             fn bitand_assign(&mut self, other: Self) {
-                self.0 = self.0 & other.0;
+                *self = Self::from_bits_retain(self.bits()).intersection(other);
             }
         }
 
         impl $crate::__private::core::ops::Sub for $PublicBitFlags {
             type Output = Self;
 
-            /// Returns the set difference of the two sets of flags.
+            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
+            ///
+            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
+            /// `difference` won't truncate `other`, but the `!` operator will.
             #[inline]
             fn sub(self, other: Self) -> Self {
                 self.difference(other)
@@ -388,17 +424,20 @@
         }
 
         impl $crate::__private::core::ops::SubAssign for $PublicBitFlags {
-            /// Disables all flags enabled in the set.
+            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
+            ///
+            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
+            /// `difference` won't truncate `other`, but the `!` operator will.
             #[inline]
             fn sub_assign(&mut self, other: Self) {
-                self.0 = self.0 & !other.0;
+                self.remove(other);
             }
         }
 
         impl $crate::__private::core::ops::Not for $PublicBitFlags {
             type Output = Self;
 
-            /// Returns the complement of this set of flags.
+            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
             #[inline]
             fn not(self) -> Self {
                 self.complement()
@@ -406,7 +445,11 @@
         }
 
         impl $crate::__private::core::iter::Extend<$PublicBitFlags> for $PublicBitFlags {
-            fn extend<T: $crate::__private::core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) {
+            /// The bitwise or (`|`) of the bits in each flags value.
+            fn extend<T: $crate::__private::core::iter::IntoIterator<Item = Self>>(
+                &mut self,
+                iterator: T,
+            ) {
                 for item in iterator {
                     self.insert(item)
                 }
@@ -414,7 +457,10 @@
         }
 
         impl $crate::__private::core::iter::FromIterator<$PublicBitFlags> for $PublicBitFlags {
-            fn from_iter<T: $crate::__private::core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self {
+            /// The bitwise or (`|`) of the bits in each flags value.
+            fn from_iter<T: $crate::__private::core::iter::IntoIterator<Item = Self>>(
+                iterator: T,
+            ) -> Self {
                 use $crate::__private::core::iter::Extend;
 
                 let mut result = Self::empty();
@@ -426,41 +472,64 @@
 }
 
 /// Implement constants on the public (user-facing) bitflags type.
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_consts {
     (
         $PublicBitFlags:ident: $T:ty {
             $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident = $value:expr;
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:tt = $value:expr;
             )*
         }
     ) => {
         impl $PublicBitFlags {
             $(
-                $(#[$attr $($args)*])*
-                #[allow(
-                    deprecated,
-                    non_upper_case_globals,
-                )]
-                pub const $Flag: Self = Self::from_bits_retain($value);
+                $crate::__bitflags_flag!({
+                    name: $Flag,
+                    named: {
+                        $(#[$inner $($args)*])*
+                        #[allow(
+                            deprecated,
+                            non_upper_case_globals,
+                        )]
+                        pub const $Flag: Self = Self::from_bits_retain($value);
+                    },
+                    unnamed: {},
+                });
             )*
         }
 
         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)
-                        }
-                    ),
+                    $crate::__bitflags_flag!({
+                        name: $Flag,
+                        named: {
+                            $crate::__bitflags_expr_safe_attrs!(
+                                $(#[$inner $($args)*])*
+                                {
+                                    #[allow(
+                                        deprecated,
+                                        non_upper_case_globals,
+                                    )]
+                                    $crate::Flag::new($crate::__private::core::stringify!($Flag), $PublicBitFlags::$Flag)
+                                }
+                            )
+                        },
+                        unnamed: {
+                            $crate::__bitflags_expr_safe_attrs!(
+                                $(#[$inner $($args)*])*
+                                {
+                                    #[allow(
+                                        deprecated,
+                                        non_upper_case_globals,
+                                    )]
+                                    $crate::Flag::new("", $PublicBitFlags::from_bits_retain($value))
+                                }
+                            )
+                        },
+                    }),
                 )*
             ];
 
diff --git a/src/tests.rs b/src/tests.rs
new file mode 100644
index 0000000..ed52ad4
--- /dev/null
+++ b/src/tests.rs
@@ -0,0 +1,131 @@
+mod all;
+mod bits;
+mod complement;
+mod contains;
+mod difference;
+mod empty;
+mod eq;
+mod extend;
+mod flags;
+mod fmt;
+mod from_bits;
+mod from_bits_retain;
+mod from_bits_truncate;
+mod from_name;
+mod insert;
+mod intersection;
+mod intersects;
+mod is_all;
+mod is_empty;
+mod iter;
+mod parser;
+mod remove;
+mod symmetric_difference;
+mod union;
+
+bitflags! {
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestFlags: u8 {
+        /// 1
+        const A = 1;
+
+        /// 1 << 1
+        const B = 1 << 1;
+
+        /// 1 << 2
+        const C = 1 << 2;
+
+        /// 1 | (1 << 1) | (1 << 2)
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestFlagsInvert: u8 {
+        /// 1 | (1 << 1) | (1 << 2)
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+
+        /// 1
+        const A = 1;
+
+        /// 1 << 1
+        const B = 1 << 1;
+
+        /// 1 << 2
+        const C = 1 << 2;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestZero: u8 {
+        /// 0
+        const ZERO = 0;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestZeroOne: u8 {
+        /// 0
+        const ZERO = 0;
+
+        /// 1
+        const ONE = 1;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestUnicode: u8 {
+        /// 1
+        const 一 = 1;
+
+        /// 2
+        const 二 = 1 << 1;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestEmpty: u8 {}
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestOverlapping: u8 {
+        /// 1 | (1 << 1)
+        const AB = 1 | (1 << 1);
+
+        /// (1 << 1) | (1 << 2)
+        const BC = (1 << 1) | (1 << 2);
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestOverlappingFull: u8 {
+        /// 1
+        const A = 1;
+
+        /// 1
+        const B = 1;
+
+        /// 1
+        const C = 1;
+
+        /// 2
+        const D = 1 << 1;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestExternal: u8 {
+        /// 1
+        const A = 1;
+
+        /// 1 << 1
+        const B = 1 << 1;
+
+        /// 1 << 2
+        const C = 1 << 2;
+
+        /// 1 | (1 << 1) | (1 << 2)
+        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
+
+        /// External
+        const _ = !0;
+    }
+
+    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+    pub struct TestExternalFull: u8 {
+        /// External
+        const _ = !0;
+    }
+}
diff --git a/src/tests/all.rs b/src/tests/all.rs
new file mode 100644
index 0000000..cceb93a
--- /dev/null
+++ b/src/tests/all.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(1 | 1 << 1 | 1 << 2, TestFlags::all);
+
+    case(0, TestZero::all);
+
+    case(0, TestEmpty::all);
+
+    case(!0, TestExternal::all);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(expected, inherent().bits(), "T::all()");
+    assert_eq!(expected, T::all().bits(), "Flags::all()");
+}
diff --git a/src/tests/bits.rs b/src/tests/bits.rs
new file mode 100644
index 0000000..678f153
--- /dev/null
+++ b/src/tests/bits.rs
@@ -0,0 +1,36 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(0, TestFlags::empty(), TestFlags::bits);
+
+    case(1, TestFlags::A, TestFlags::bits);
+    case(1 | 1 << 1 | 1 << 2, TestFlags::ABC, TestFlags::bits);
+
+    case(!0, TestFlags::from_bits_retain(u8::MAX), TestFlags::bits);
+    case(1 << 3, TestFlags::from_bits_retain(1 << 3), TestFlags::bits);
+
+    case(1 << 3, TestZero::from_bits_retain(1 << 3), TestZero::bits);
+
+    case(1 << 3, TestEmpty::from_bits_retain(1 << 3), TestEmpty::bits);
+
+    case(
+        1 << 4 | 1 << 6,
+        TestExternal::from_bits_retain(1 << 4 | 1 << 6),
+        TestExternal::bits,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(
+    expected: T::Bits,
+    value: T,
+    inherent: impl FnOnce(&T) -> T::Bits,
+) where
+    T::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(expected, inherent(&value), "{:?}.bits()", value);
+    assert_eq!(expected, Flags::bits(&value), "Flags::bits({:?})", value);
+}
diff --git a/src/tests/complement.rs b/src/tests/complement.rs
new file mode 100644
index 0000000..ac7a421
--- /dev/null
+++ b/src/tests/complement.rs
@@ -0,0 +1,53 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(0, TestFlags::all(), TestFlags::complement);
+    case(0, TestFlags::from_bits_retain(!0), TestFlags::complement);
+
+    case(1 | 1 << 1, TestFlags::C, TestFlags::complement);
+    case(
+        1 | 1 << 1,
+        TestFlags::C | TestFlags::from_bits_retain(1 << 3),
+        TestFlags::complement,
+    );
+
+    case(
+        1 | 1 << 1 | 1 << 2,
+        TestFlags::empty(),
+        TestFlags::complement,
+    );
+    case(
+        1 | 1 << 1 | 1 << 2,
+        TestFlags::from_bits_retain(1 << 3),
+        TestFlags::complement,
+    );
+
+    case(0, TestZero::empty(), TestZero::complement);
+
+    case(0, TestEmpty::empty(), TestEmpty::complement);
+
+    case(1 << 2, TestOverlapping::AB, TestOverlapping::complement);
+
+    case(!0, TestExternal::empty(), TestExternal::complement);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Not<Output = T> + Copy>(
+    expected: T::Bits,
+    value: T,
+    inherent: impl FnOnce(T) -> T,
+) where
+    T::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(expected, inherent(value).bits(), "{:?}.complement()", value);
+    assert_eq!(
+        expected,
+        Flags::complement(value).bits(),
+        "Flags::complement({:?})",
+        value
+    );
+    assert_eq!(expected, (!value).bits(), "!{:?}", value);
+}
diff --git a/src/tests/contains.rs b/src/tests/contains.rs
new file mode 100644
index 0000000..12428dd
--- /dev/null
+++ b/src/tests/contains.rs
@@ -0,0 +1,108 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::empty(), true),
+            (TestFlags::A, false),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::from_bits_retain(1 << 3), false),
+        ],
+        TestFlags::contains,
+    );
+
+    case(
+        TestFlags::A,
+        &[
+            (TestFlags::empty(), true),
+            (TestFlags::A, true),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::ABC, false),
+            (TestFlags::from_bits_retain(1 << 3), false),
+            (TestFlags::from_bits_retain(1 | (1 << 3)), false),
+        ],
+        TestFlags::contains,
+    );
+
+    case(
+        TestFlags::ABC,
+        &[
+            (TestFlags::empty(), true),
+            (TestFlags::A, true),
+            (TestFlags::B, true),
+            (TestFlags::C, true),
+            (TestFlags::ABC, true),
+            (TestFlags::from_bits_retain(1 << 3), false),
+        ],
+        TestFlags::contains,
+    );
+
+    case(
+        TestFlags::from_bits_retain(1 << 3),
+        &[
+            (TestFlags::empty(), true),
+            (TestFlags::A, false),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::from_bits_retain(1 << 3), true),
+        ],
+        TestFlags::contains,
+    );
+
+    case(
+        TestZero::ZERO,
+        &[(TestZero::ZERO, true)],
+        TestZero::contains,
+    );
+
+    case(
+        TestOverlapping::AB,
+        &[
+            (TestOverlapping::AB, true),
+            (TestOverlapping::BC, false),
+            (TestOverlapping::from_bits_retain(1 << 1), true),
+        ],
+        TestOverlapping::contains,
+    );
+
+    case(
+        TestExternal::all(),
+        &[
+            (TestExternal::A, true),
+            (TestExternal::B, true),
+            (TestExternal::C, true),
+            (TestExternal::from_bits_retain(1 << 5 | 1 << 7), true),
+        ],
+        TestExternal::contains,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+    value: T,
+    inputs: &[(T, bool)],
+    mut inherent: impl FnMut(&T, T) -> bool,
+) {
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent(&value, *input),
+            "{:?}.contains({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::contains(&value, *input),
+            "Flags::contains({:?}, {:?})",
+            value,
+            input
+        );
+    }
+}
diff --git a/src/tests/difference.rs b/src/tests/difference.rs
new file mode 100644
index 0000000..6ce9c0b
--- /dev/null
+++ b/src/tests/difference.rs
@@ -0,0 +1,92 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::A | TestFlags::B,
+        &[
+            (TestFlags::A, 1 << 1),
+            (TestFlags::B, 1),
+            (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+        ],
+        TestFlags::difference,
+    );
+
+    case(
+        TestFlags::from_bits_retain(1 | 1 << 3),
+        &[
+            (TestFlags::A, 1 << 3),
+            (TestFlags::from_bits_retain(1 << 3), 1),
+        ],
+        TestFlags::difference,
+    );
+
+    case(
+        TestExternal::from_bits_retain(!0),
+        &[(TestExternal::A, 0b1111_1110)],
+        TestExternal::difference,
+    );
+
+    assert_eq!(
+        0b1111_1110,
+        (TestExternal::from_bits_retain(!0) & !TestExternal::A).bits()
+    );
+
+    assert_eq!(
+        0b1111_1110,
+        (TestFlags::from_bits_retain(!0).difference(TestFlags::A)).bits()
+    );
+
+    // The `!` operator unsets bits that don't correspond to known flags
+    assert_eq!(
+        1 << 1 | 1 << 2,
+        (TestFlags::from_bits_retain(!0) & !TestFlags::A).bits()
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::Sub<Output = T> + std::ops::SubAssign + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent: impl FnMut(T, T) -> T,
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent(value, *input).bits(),
+            "{:?}.difference({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::difference(value, *input).bits(),
+            "Flags::difference({:?}, {:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            (value - *input).bits(),
+            "{:?} - {:?}",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                value -= *input;
+                value
+            }
+            .bits(),
+            "{:?} -= {:?}",
+            value,
+            input,
+        );
+    }
+}
diff --git a/src/tests/empty.rs b/src/tests/empty.rs
new file mode 100644
index 0000000..57fb1c7
--- /dev/null
+++ b/src/tests/empty.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(0, TestFlags::empty);
+
+    case(0, TestZero::empty);
+
+    case(0, TestEmpty::empty);
+
+    case(0, TestExternal::empty);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, inherent: impl FnOnce() -> T)
+where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(expected, inherent().bits(), "T::empty()");
+    assert_eq!(expected, T::empty().bits(), "Flags::empty()");
+}
diff --git a/src/tests/eq.rs b/src/tests/eq.rs
new file mode 100644
index 0000000..9779af7
--- /dev/null
+++ b/src/tests/eq.rs
@@ -0,0 +1,10 @@
+use super::*;
+
+#[test]
+fn cases() {
+    assert_eq!(TestFlags::empty(), TestFlags::empty());
+    assert_eq!(TestFlags::all(), TestFlags::all());
+
+    assert!(TestFlags::from_bits_retain(1) < TestFlags::from_bits_retain(2));
+    assert!(TestFlags::from_bits_retain(2) > TestFlags::from_bits_retain(1));
+}
diff --git a/src/tests/extend.rs b/src/tests/extend.rs
new file mode 100644
index 0000000..869dc17
--- /dev/null
+++ b/src/tests/extend.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+#[test]
+fn cases() {
+    let mut flags = TestFlags::empty();
+
+    flags.extend(TestFlags::A);
+
+    assert_eq!(TestFlags::A, flags);
+
+    flags.extend(TestFlags::A | TestFlags::B | TestFlags::C);
+
+    assert_eq!(TestFlags::ABC, flags);
+
+    flags.extend(TestFlags::from_bits_retain(1 << 5));
+
+    assert_eq!(TestFlags::ABC | TestFlags::from_bits_retain(1 << 5), flags);
+}
+
+mod external {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        let mut flags = TestExternal::empty();
+
+        flags.extend(TestExternal::A);
+
+        assert_eq!(TestExternal::A, flags);
+
+        flags.extend(TestExternal::A | TestExternal::B | TestExternal::C);
+
+        assert_eq!(TestExternal::ABC, flags);
+
+        flags.extend(TestExternal::from_bits_retain(1 << 5));
+
+        assert_eq!(
+            TestExternal::ABC | TestExternal::from_bits_retain(1 << 5),
+            flags
+        );
+    }
+}
diff --git a/src/tests/flags.rs b/src/tests/flags.rs
new file mode 100644
index 0000000..7a625b3
--- /dev/null
+++ b/src/tests/flags.rs
@@ -0,0 +1,46 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    let flags = TestFlags::FLAGS
+        .iter()
+        .map(|flag| (flag.name(), flag.value().bits()))
+        .collect::<Vec<_>>();
+
+    assert_eq!(
+        vec![
+            ("A", 1u8),
+            ("B", 1 << 1),
+            ("C", 1 << 2),
+            ("ABC", 1 | 1 << 1 | 1 << 2),
+        ],
+        flags,
+    );
+
+    assert_eq!(0, TestEmpty::FLAGS.iter().count());
+}
+
+mod external {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        let flags = TestExternal::FLAGS
+            .iter()
+            .map(|flag| (flag.name(), flag.value().bits()))
+            .collect::<Vec<_>>();
+
+        assert_eq!(
+            vec![
+                ("A", 1u8),
+                ("B", 1 << 1),
+                ("C", 1 << 2),
+                ("ABC", 1 | 1 << 1 | 1 << 2),
+                ("", !0),
+            ],
+            flags,
+        );
+    }
+}
diff --git a/src/tests/fmt.rs b/src/tests/fmt.rs
new file mode 100644
index 0000000..ed45718
--- /dev/null
+++ b/src/tests/fmt.rs
@@ -0,0 +1,97 @@
+use super::*;
+
+#[test]
+fn cases() {
+    case(TestFlags::empty(), "TestFlags(0x0)", "0", "0", "0", "0");
+    case(TestFlags::A, "TestFlags(A)", "1", "1", "1", "1");
+    case(
+        TestFlags::all(),
+        "TestFlags(A | B | C)",
+        "7",
+        "7",
+        "7",
+        "111",
+    );
+    case(
+        TestFlags::from_bits_retain(1 << 3),
+        "TestFlags(0x8)",
+        "8",
+        "8",
+        "10",
+        "1000",
+    );
+    case(
+        TestFlags::A | TestFlags::from_bits_retain(1 << 3),
+        "TestFlags(A | 0x8)",
+        "9",
+        "9",
+        "11",
+        "1001",
+    );
+
+    case(TestZero::ZERO, "TestZero(0x0)", "0", "0", "0", "0");
+    case(
+        TestZero::ZERO | TestZero::from_bits_retain(1),
+        "TestZero(0x1)",
+        "1",
+        "1",
+        "1",
+        "1",
+    );
+
+    case(TestZeroOne::ONE, "TestZeroOne(ONE)", "1", "1", "1", "1");
+
+    case(
+        TestOverlapping::from_bits_retain(1 << 1),
+        "TestOverlapping(0x2)",
+        "2",
+        "2",
+        "2",
+        "10",
+    );
+
+    case(
+        TestExternal::from_bits_retain(1 | 1 << 1 | 1 << 3),
+        "TestExternal(A | B | 0x8)",
+        "B",
+        "b",
+        "13",
+        "1011",
+    );
+
+    case(
+        TestExternal::all(),
+        "TestExternal(A | B | C | 0xf8)",
+        "FF",
+        "ff",
+        "377",
+        "11111111",
+    );
+
+    case(
+        TestExternalFull::all(),
+        "TestExternalFull(0xff)",
+        "FF",
+        "ff",
+        "377",
+        "11111111",
+    );
+}
+
+#[track_caller]
+fn case<
+    T: std::fmt::Debug + std::fmt::UpperHex + std::fmt::LowerHex + std::fmt::Octal + std::fmt::Binary,
+>(
+    value: T,
+    debug: &str,
+    uhex: &str,
+    lhex: &str,
+    oct: &str,
+    bin: &str,
+) {
+    assert_eq!(debug, format!("{:?}", value));
+    assert_eq!(uhex, format!("{:X}", value));
+    assert_eq!(lhex, format!("{:x}", value));
+    assert_eq!(oct, format!("{:o}", value));
+    assert_eq!(bin, format!("{:b}", value));
+}
diff --git a/src/tests/from_bits.rs b/src/tests/from_bits.rs
new file mode 100644
index 0000000..dada9af
--- /dev/null
+++ b/src/tests/from_bits.rs
@@ -0,0 +1,45 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(Some(0), 0, TestFlags::from_bits);
+    case(Some(1), 1, TestFlags::from_bits);
+    case(
+        Some(1 | 1 << 1 | 1 << 2),
+        1 | 1 << 1 | 1 << 2,
+        TestFlags::from_bits,
+    );
+
+    case(None, 1 << 3, TestFlags::from_bits);
+    case(None, 1 | 1 << 3, TestFlags::from_bits);
+
+    case(Some(1 | 1 << 1), 1 | 1 << 1, TestOverlapping::from_bits);
+
+    case(Some(1 << 1), 1 << 1, TestOverlapping::from_bits);
+
+    case(Some(1 << 5), 1 << 5, TestExternal::from_bits);
+}
+
+#[track_caller]
+fn case<T: Flags>(
+    expected: Option<T::Bits>,
+    input: T::Bits,
+    inherent: impl FnOnce(T::Bits) -> Option<T>,
+) where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(
+        expected,
+        inherent(input).map(|f| f.bits()),
+        "T::from_bits({:?})",
+        input
+    );
+    assert_eq!(
+        expected,
+        T::from_bits(input).map(|f| f.bits()),
+        "Flags::from_bits({:?})",
+        input
+    );
+}
diff --git a/src/tests/from_bits_retain.rs b/src/tests/from_bits_retain.rs
new file mode 100644
index 0000000..1ae28a6
--- /dev/null
+++ b/src/tests/from_bits_retain.rs
@@ -0,0 +1,38 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(0, TestFlags::from_bits_retain);
+    case(1, TestFlags::from_bits_retain);
+    case(1 | 1 << 1 | 1 << 2, TestFlags::from_bits_retain);
+
+    case(1 << 3, TestFlags::from_bits_retain);
+    case(1 | 1 << 3, TestFlags::from_bits_retain);
+
+    case(1 | 1 << 1, TestOverlapping::from_bits_retain);
+
+    case(1 << 1, TestOverlapping::from_bits_retain);
+
+    case(1 << 5, TestExternal::from_bits_retain);
+}
+
+#[track_caller]
+fn case<T: Flags>(input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(
+        input,
+        inherent(input).bits(),
+        "T::from_bits_retain({:?})",
+        input
+    );
+    assert_eq!(
+        input,
+        T::from_bits_retain(input).bits(),
+        "Flags::from_bits_retain({:?})",
+        input
+    );
+}
diff --git a/src/tests/from_bits_truncate.rs b/src/tests/from_bits_truncate.rs
new file mode 100644
index 0000000..e4f3e53
--- /dev/null
+++ b/src/tests/from_bits_truncate.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(0, 0, TestFlags::from_bits_truncate);
+    case(1, 1, TestFlags::from_bits_truncate);
+    case(
+        1 | 1 << 1 | 1 << 2,
+        1 | 1 << 1 | 1 << 2,
+        TestFlags::from_bits_truncate,
+    );
+
+    case(0, 1 << 3, TestFlags::from_bits_truncate);
+    case(1, 1 | 1 << 3, TestFlags::from_bits_truncate);
+
+    case(1 | 1 << 1, 1 | 1 << 1, TestOverlapping::from_bits_truncate);
+
+    case(1 << 1, 1 << 1, TestOverlapping::from_bits_truncate);
+
+    case(1 << 5, 1 << 5, TestExternal::from_bits_truncate);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: T::Bits, input: T::Bits, inherent: impl FnOnce(T::Bits) -> T)
+where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(
+        expected,
+        inherent(input).bits(),
+        "T::from_bits_truncate({:?})",
+        input
+    );
+    assert_eq!(
+        expected,
+        T::from_bits_truncate(input).bits(),
+        "Flags::from_bits_truncate({:?})",
+        input
+    );
+}
diff --git a/src/tests/from_name.rs b/src/tests/from_name.rs
new file mode 100644
index 0000000..1d9a4e4
--- /dev/null
+++ b/src/tests/from_name.rs
@@ -0,0 +1,42 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(Some(1), "A", TestFlags::from_name);
+    case(Some(1 << 1), "B", TestFlags::from_name);
+    case(Some(1 | 1 << 1 | 1 << 2), "ABC", TestFlags::from_name);
+
+    case(None, "", TestFlags::from_name);
+    case(None, "a", TestFlags::from_name);
+    case(None, "0x1", TestFlags::from_name);
+    case(None, "A | B", TestFlags::from_name);
+
+    case(Some(0), "ZERO", TestZero::from_name);
+
+    case(Some(2), "二", TestUnicode::from_name);
+
+    case(None, "_", TestExternal::from_name);
+
+    case(None, "", TestExternal::from_name);
+}
+
+#[track_caller]
+fn case<T: Flags>(expected: Option<T::Bits>, input: &str, inherent: impl FnOnce(&str) -> Option<T>)
+where
+    <T as Flags>::Bits: std::fmt::Debug + PartialEq,
+{
+    assert_eq!(
+        expected,
+        inherent(input).map(|f| f.bits()),
+        "T::from_name({:?})",
+        input
+    );
+    assert_eq!(
+        expected,
+        T::from_name(input).map(|f| f.bits()),
+        "Flags::from_name({:?})",
+        input
+    );
+}
diff --git a/src/tests/insert.rs b/src/tests/insert.rs
new file mode 100644
index 0000000..b18cd17
--- /dev/null
+++ b/src/tests/insert.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::A, 1),
+            (TestFlags::A | TestFlags::B, 1 | 1 << 1),
+            (TestFlags::empty(), 0),
+            (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+        ],
+        TestFlags::insert,
+        TestFlags::set,
+    );
+
+    case(
+        TestFlags::A,
+        &[
+            (TestFlags::A, 1),
+            (TestFlags::empty(), 1),
+            (TestFlags::B, 1 | 1 << 1),
+        ],
+        TestFlags::insert,
+        TestFlags::set,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent_insert: impl FnMut(&mut T, T),
+    mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                inherent_insert(&mut value, *input);
+                value
+            }
+            .bits(),
+            "{:?}.insert({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                Flags::insert(&mut value, *input);
+                value
+            }
+            .bits(),
+            "Flags::insert({:?}, {:?})",
+            value,
+            input
+        );
+
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                inherent_set(&mut value, *input, true);
+                value
+            }
+            .bits(),
+            "{:?}.set({:?}, true)",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                Flags::set(&mut value, *input, true);
+                value
+            }
+            .bits(),
+            "Flags::set({:?}, {:?}, true)",
+            value,
+            input
+        );
+    }
+}
diff --git a/src/tests/intersection.rs b/src/tests/intersection.rs
new file mode 100644
index 0000000..10a8ae9
--- /dev/null
+++ b/src/tests/intersection.rs
@@ -0,0 +1,79 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[(TestFlags::empty(), 0), (TestFlags::all(), 0)],
+        TestFlags::intersection,
+    );
+
+    case(
+        TestFlags::all(),
+        &[
+            (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+            (TestFlags::A, 1),
+            (TestFlags::from_bits_retain(1 << 3), 0),
+        ],
+        TestFlags::intersection,
+    );
+
+    case(
+        TestFlags::from_bits_retain(1 << 3),
+        &[(TestFlags::from_bits_retain(1 << 3), 1 << 3)],
+        TestFlags::intersection,
+    );
+
+    case(
+        TestOverlapping::AB,
+        &[(TestOverlapping::BC, 1 << 1)],
+        TestOverlapping::intersection,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitAnd<Output = T> + std::ops::BitAndAssign + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent: impl FnMut(T, T) -> T,
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent(value, *input).bits(),
+            "{:?}.intersection({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::intersection(value, *input).bits(),
+            "Flags::intersection({:?}, {:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            (value & *input).bits(),
+            "{:?} & {:?}",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                value &= *input;
+                value
+            }
+            .bits(),
+            "{:?} &= {:?}",
+            value,
+            input,
+        );
+    }
+}
diff --git a/src/tests/intersects.rs b/src/tests/intersects.rs
new file mode 100644
index 0000000..fe90798
--- /dev/null
+++ b/src/tests/intersects.rs
@@ -0,0 +1,91 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::empty(), false),
+            (TestFlags::A, false),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::from_bits_retain(1 << 3), false),
+        ],
+        TestFlags::intersects,
+    );
+
+    case(
+        TestFlags::A,
+        &[
+            (TestFlags::empty(), false),
+            (TestFlags::A, true),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::ABC, true),
+            (TestFlags::from_bits_retain(1 << 3), false),
+            (TestFlags::from_bits_retain(1 | (1 << 3)), true),
+        ],
+        TestFlags::intersects,
+    );
+
+    case(
+        TestFlags::ABC,
+        &[
+            (TestFlags::empty(), false),
+            (TestFlags::A, true),
+            (TestFlags::B, true),
+            (TestFlags::C, true),
+            (TestFlags::ABC, true),
+            (TestFlags::from_bits_retain(1 << 3), false),
+        ],
+        TestFlags::intersects,
+    );
+
+    case(
+        TestFlags::from_bits_retain(1 << 3),
+        &[
+            (TestFlags::empty(), false),
+            (TestFlags::A, false),
+            (TestFlags::B, false),
+            (TestFlags::C, false),
+            (TestFlags::from_bits_retain(1 << 3), true),
+        ],
+        TestFlags::intersects,
+    );
+
+    case(
+        TestOverlapping::AB,
+        &[
+            (TestOverlapping::AB, true),
+            (TestOverlapping::BC, true),
+            (TestOverlapping::from_bits_retain(1 << 1), true),
+        ],
+        TestOverlapping::intersects,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+    value: T,
+    inputs: &[(T, bool)],
+    mut inherent: impl FnMut(&T, T) -> bool,
+) {
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent(&value, *input),
+            "{:?}.intersects({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::intersects(&value, *input),
+            "Flags::intersects({:?}, {:?})",
+            value,
+            input
+        );
+    }
+}
diff --git a/src/tests/is_all.rs b/src/tests/is_all.rs
new file mode 100644
index 0000000..382a458
--- /dev/null
+++ b/src/tests/is_all.rs
@@ -0,0 +1,32 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(false, TestFlags::empty(), TestFlags::is_all);
+    case(false, TestFlags::A, TestFlags::is_all);
+
+    case(true, TestFlags::ABC, TestFlags::is_all);
+
+    case(
+        true,
+        TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+        TestFlags::is_all,
+    );
+
+    case(true, TestZero::empty(), TestZero::is_all);
+
+    case(true, TestEmpty::empty(), TestEmpty::is_all);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+    assert_eq!(expected, inherent(&value), "{:?}.is_all()", value);
+    assert_eq!(
+        expected,
+        Flags::is_all(&value),
+        "Flags::is_all({:?})",
+        value
+    );
+}
diff --git a/src/tests/is_empty.rs b/src/tests/is_empty.rs
new file mode 100644
index 0000000..92165f1
--- /dev/null
+++ b/src/tests/is_empty.rs
@@ -0,0 +1,31 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(true, TestFlags::empty(), TestFlags::is_empty);
+
+    case(false, TestFlags::A, TestFlags::is_empty);
+    case(false, TestFlags::ABC, TestFlags::is_empty);
+    case(
+        false,
+        TestFlags::from_bits_retain(1 << 3),
+        TestFlags::is_empty,
+    );
+
+    case(true, TestZero::empty(), TestZero::is_empty);
+
+    case(true, TestEmpty::empty(), TestEmpty::is_empty);
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug>(expected: bool, value: T, inherent: impl FnOnce(&T) -> bool) {
+    assert_eq!(expected, inherent(&value), "{:?}.is_empty()", value);
+    assert_eq!(
+        expected,
+        Flags::is_empty(&value),
+        "Flags::is_empty({:?})",
+        value
+    );
+}
diff --git a/src/tests/iter.rs b/src/tests/iter.rs
new file mode 100644
index 0000000..54b1d27
--- /dev/null
+++ b/src/tests/iter.rs
@@ -0,0 +1,209 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+    for a in 0u8..=255 {
+        for b in 0u8..=255 {
+            let f = TestFlags::from_bits_retain(a | b);
+
+            assert_eq!(f, f.iter().collect::<TestFlags>());
+            assert_eq!(
+                TestFlags::from_bits_truncate(f.bits()),
+                f.iter_names().map(|(_, f)| f).collect::<TestFlags>()
+            );
+
+            let f = TestExternal::from_bits_retain(a | b);
+
+            assert_eq!(f, f.iter().collect::<TestExternal>());
+        }
+    }
+}
+
+mod collect {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        assert_eq!(0, [].into_iter().collect::<TestFlags>().bits());
+
+        assert_eq!(1, [TestFlags::A,].into_iter().collect::<TestFlags>().bits());
+
+        assert_eq!(
+            1 | 1 << 1 | 1 << 2,
+            [TestFlags::A, TestFlags::B | TestFlags::C,]
+                .into_iter()
+                .collect::<TestFlags>()
+                .bits()
+        );
+
+        assert_eq!(
+            1 | 1 << 3,
+            [
+                TestFlags::from_bits_retain(1 << 3),
+                TestFlags::empty(),
+                TestFlags::A,
+            ]
+            .into_iter()
+            .collect::<TestFlags>()
+            .bits()
+        );
+
+        assert_eq!(
+            1 << 5 | 1 << 7,
+            [
+                TestExternal::empty(),
+                TestExternal::from_bits_retain(1 << 5),
+                TestExternal::from_bits_retain(1 << 7),
+            ]
+            .into_iter()
+            .collect::<TestExternal>()
+            .bits()
+        );
+    }
+}
+
+mod iter {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        case(&[], TestFlags::empty(), TestFlags::iter);
+
+        case(&[1], TestFlags::A, TestFlags::iter);
+        case(&[1, 1 << 1], TestFlags::A | TestFlags::B, TestFlags::iter);
+        case(
+            &[1, 1 << 1, 1 << 3],
+            TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+            TestFlags::iter,
+        );
+
+        case(&[1, 1 << 1, 1 << 2], TestFlags::ABC, TestFlags::iter);
+        case(
+            &[1, 1 << 1, 1 << 2, 1 << 3],
+            TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+            TestFlags::iter,
+        );
+
+        case(
+            &[1 | 1 << 1 | 1 << 2],
+            TestFlagsInvert::ABC,
+            TestFlagsInvert::iter,
+        );
+
+        case(&[], TestZero::ZERO, TestZero::iter);
+
+        case(
+            &[1, 1 << 1, 1 << 2, 0b1111_1000],
+            TestExternal::all(),
+            TestExternal::iter,
+        );
+    }
+
+    #[track_caller]
+    fn case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>(
+        expected: &[T::Bits],
+        value: T,
+        inherent: impl FnOnce(&T) -> crate::iter::Iter<T>,
+    ) where
+        T::Bits: std::fmt::Debug + PartialEq,
+    {
+        assert_eq!(
+            expected,
+            inherent(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+            "{:?}.iter()",
+            value
+        );
+        assert_eq!(
+            expected,
+            Flags::iter(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+            "Flags::iter({:?})",
+            value
+        );
+        assert_eq!(
+            expected,
+            value.into_iter().map(|f| f.bits()).collect::<Vec<_>>(),
+            "{:?}.into_iter()",
+            value
+        );
+    }
+}
+
+mod iter_names {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        case(&[], TestFlags::empty(), TestFlags::iter_names);
+
+        case(&[("A", 1)], TestFlags::A, TestFlags::iter_names);
+        case(
+            &[("A", 1), ("B", 1 << 1)],
+            TestFlags::A | TestFlags::B,
+            TestFlags::iter_names,
+        );
+        case(
+            &[("A", 1), ("B", 1 << 1)],
+            TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+            TestFlags::iter_names,
+        );
+
+        case(
+            &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+            TestFlags::ABC,
+            TestFlags::iter_names,
+        );
+        case(
+            &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+            TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+            TestFlags::iter_names,
+        );
+
+        case(
+            &[("ABC", 1 | 1 << 1 | 1 << 2)],
+            TestFlagsInvert::ABC,
+            TestFlagsInvert::iter_names,
+        );
+
+        case(&[], TestZero::ZERO, TestZero::iter_names);
+
+        case(
+            &[("A", 1)],
+            TestOverlappingFull::A,
+            TestOverlappingFull::iter_names,
+        );
+        case(
+            &[("A", 1), ("D", 1 << 1)],
+            TestOverlappingFull::A | TestOverlappingFull::D,
+            TestOverlappingFull::iter_names,
+        );
+    }
+
+    #[track_caller]
+    fn case<T: Flags + std::fmt::Debug>(
+        expected: &[(&'static str, T::Bits)],
+        value: T,
+        inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>,
+    ) where
+        T::Bits: std::fmt::Debug + PartialEq,
+    {
+        assert_eq!(
+            expected,
+            inherent(&value)
+                .map(|(n, f)| (n, f.bits()))
+                .collect::<Vec<_>>(),
+            "{:?}.iter_names()",
+            value
+        );
+        assert_eq!(
+            expected,
+            Flags::iter_names(&value)
+                .map(|(n, f)| (n, f.bits()))
+                .collect::<Vec<_>>(),
+            "Flags::iter_names({:?})",
+            value
+        );
+    }
+}
diff --git a/src/tests/parser.rs b/src/tests/parser.rs
new file mode 100644
index 0000000..b370785
--- /dev/null
+++ b/src/tests/parser.rs
@@ -0,0 +1,116 @@
+use super::*;
+
+use crate::{
+    parser::{from_str, to_writer},
+    Flags,
+};
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+    let mut s = String::new();
+
+    for a in 0u8..=255 {
+        for b in 0u8..=255 {
+            let f = TestFlags::from_bits_retain(a | b);
+
+            s.clear();
+            to_writer(&f, &mut s).unwrap();
+
+            assert_eq!(f, from_str::<TestFlags>(&s).unwrap());
+        }
+    }
+}
+
+mod from_str {
+    use super::*;
+
+    #[test]
+    fn valid() {
+        assert_eq!(0, from_str::<TestFlags>("").unwrap().bits());
+
+        assert_eq!(1, from_str::<TestFlags>("A").unwrap().bits());
+        assert_eq!(1, from_str::<TestFlags>(" A ").unwrap().bits());
+        assert_eq!(
+            1 | 1 << 1 | 1 << 2,
+            from_str::<TestFlags>("A | B | C").unwrap().bits()
+        );
+        assert_eq!(
+            1 | 1 << 1 | 1 << 2,
+            from_str::<TestFlags>("A\n|\tB\r\n|   C ").unwrap().bits()
+        );
+        assert_eq!(
+            1 | 1 << 1 | 1 << 2,
+            from_str::<TestFlags>("A|B|C").unwrap().bits()
+        );
+
+        assert_eq!(1 << 3, from_str::<TestFlags>("0x8").unwrap().bits());
+        assert_eq!(1 | 1 << 3, from_str::<TestFlags>("A | 0x8").unwrap().bits());
+        assert_eq!(
+            1 | 1 << 1 | 1 << 3,
+            from_str::<TestFlags>("0x1 | 0x8 | B").unwrap().bits()
+        );
+
+        assert_eq!(
+            1 | 1 << 1,
+            from_str::<TestUnicode>("一 | 二").unwrap().bits()
+        );
+    }
+
+    #[test]
+    fn invalid() {
+        assert!(from_str::<TestFlags>("a")
+            .unwrap_err()
+            .to_string()
+            .starts_with("unrecognized named flag"));
+        assert!(from_str::<TestFlags>("A & B")
+            .unwrap_err()
+            .to_string()
+            .starts_with("unrecognized named flag"));
+
+        assert!(from_str::<TestFlags>("0xg")
+            .unwrap_err()
+            .to_string()
+            .starts_with("invalid hex flag"));
+        assert!(from_str::<TestFlags>("0xffffffffffff")
+            .unwrap_err()
+            .to_string()
+            .starts_with("invalid hex flag"));
+    }
+}
+
+mod to_writer {
+    use super::*;
+
+    #[test]
+    fn cases() {
+        assert_eq!("", write(TestFlags::empty()));
+        assert_eq!("A", write(TestFlags::A));
+        assert_eq!("A | B | C", write(TestFlags::all()));
+        assert_eq!("0x8", write(TestFlags::from_bits_retain(1 << 3)));
+        assert_eq!(
+            "A | 0x8",
+            write(TestFlags::A | TestFlags::from_bits_retain(1 << 3))
+        );
+
+        assert_eq!("", write(TestZero::ZERO));
+
+        assert_eq!("ABC", write(TestFlagsInvert::all()));
+
+        assert_eq!("A", write(TestOverlappingFull::C));
+        assert_eq!(
+            "A | D",
+            write(TestOverlappingFull::C | TestOverlappingFull::D)
+        );
+    }
+
+    fn write<F: Flags>(value: F) -> String
+    where
+        F::Bits: crate::parser::WriteHex,
+    {
+        let mut s = String::new();
+
+        to_writer(&value, &mut s).unwrap();
+        s
+    }
+}
diff --git a/src/tests/remove.rs b/src/tests/remove.rs
new file mode 100644
index 0000000..574b1ed
--- /dev/null
+++ b/src/tests/remove.rs
@@ -0,0 +1,100 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::A, 0),
+            (TestFlags::empty(), 0),
+            (TestFlags::from_bits_retain(1 << 3), 0),
+        ],
+        TestFlags::remove,
+        TestFlags::set,
+    );
+
+    case(
+        TestFlags::A,
+        &[
+            (TestFlags::A, 0),
+            (TestFlags::empty(), 1),
+            (TestFlags::B, 1),
+        ],
+        TestFlags::remove,
+        TestFlags::set,
+    );
+
+    case(
+        TestFlags::ABC,
+        &[
+            (TestFlags::A, 1 << 1 | 1 << 2),
+            (TestFlags::A | TestFlags::C, 1 << 1),
+        ],
+        TestFlags::remove,
+        TestFlags::set,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent_remove: impl FnMut(&mut T, T),
+    mut inherent_set: impl FnMut(&mut T, T, bool),
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                inherent_remove(&mut value, *input);
+                value
+            }
+            .bits(),
+            "{:?}.remove({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                Flags::remove(&mut value, *input);
+                value
+            }
+            .bits(),
+            "Flags::remove({:?}, {:?})",
+            value,
+            input
+        );
+
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                inherent_set(&mut value, *input, false);
+                value
+            }
+            .bits(),
+            "{:?}.set({:?}, false)",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                Flags::set(&mut value, *input, false);
+                value
+            }
+            .bits(),
+            "Flags::set({:?}, {:?}, false)",
+            value,
+            input
+        );
+    }
+}
diff --git a/src/tests/symmetric_difference.rs b/src/tests/symmetric_difference.rs
new file mode 100644
index 0000000..75e9123
--- /dev/null
+++ b/src/tests/symmetric_difference.rs
@@ -0,0 +1,110 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::empty(), 0),
+            (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+            (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+        ],
+        TestFlags::symmetric_difference,
+        TestFlags::toggle,
+    );
+
+    case(
+        TestFlags::A,
+        &[
+            (TestFlags::empty(), 1),
+            (TestFlags::A, 0),
+            (TestFlags::all(), 1 << 1 | 1 << 2),
+        ],
+        TestFlags::symmetric_difference,
+        TestFlags::toggle,
+    );
+
+    case(
+        TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+        &[
+            (TestFlags::ABC, 1 << 2 | 1 << 3),
+            (TestFlags::from_bits_retain(1 << 3), 1 | 1 << 1),
+        ],
+        TestFlags::symmetric_difference,
+        TestFlags::toggle,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitXor<Output = T> + std::ops::BitXorAssign + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent_sym_diff: impl FnMut(T, T) -> T,
+    mut inherent_toggle: impl FnMut(&mut T, T),
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent_sym_diff(value, *input).bits(),
+            "{:?}.symmetric_difference({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::symmetric_difference(value, *input).bits(),
+            "Flags::symmetric_difference({:?}, {:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            (value ^ *input).bits(),
+            "{:?} ^ {:?}",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                value ^= *input;
+                value
+            }
+            .bits(),
+            "{:?} ^= {:?}",
+            value,
+            input,
+        );
+
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                inherent_toggle(&mut value, *input);
+                value
+            }
+            .bits(),
+            "{:?}.toggle({:?})",
+            value,
+            input,
+        );
+
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                Flags::toggle(&mut value, *input);
+                value
+            }
+            .bits(),
+            "{:?}.toggle({:?})",
+            value,
+            input,
+        );
+    }
+}
diff --git a/src/tests/union.rs b/src/tests/union.rs
new file mode 100644
index 0000000..6190681
--- /dev/null
+++ b/src/tests/union.rs
@@ -0,0 +1,71 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+fn cases() {
+    case(
+        TestFlags::empty(),
+        &[
+            (TestFlags::A, 1),
+            (TestFlags::all(), 1 | 1 << 1 | 1 << 2),
+            (TestFlags::empty(), 0),
+            (TestFlags::from_bits_retain(1 << 3), 1 << 3),
+        ],
+        TestFlags::union,
+    );
+
+    case(
+        TestFlags::A | TestFlags::C,
+        &[
+            (TestFlags::A | TestFlags::B, 1 | 1 << 1 | 1 << 2),
+            (TestFlags::A, 1 | 1 << 2),
+        ],
+        TestFlags::union,
+    );
+}
+
+#[track_caller]
+fn case<T: Flags + std::fmt::Debug + std::ops::BitOr<Output = T> + std::ops::BitOrAssign + Copy>(
+    value: T,
+    inputs: &[(T, T::Bits)],
+    mut inherent: impl FnMut(T, T) -> T,
+) where
+    T::Bits: std::fmt::Debug + PartialEq + Copy,
+{
+    for (input, expected) in inputs {
+        assert_eq!(
+            *expected,
+            inherent(value, *input).bits(),
+            "{:?}.union({:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            Flags::union(value, *input).bits(),
+            "Flags::union({:?}, {:?})",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            (value | *input).bits(),
+            "{:?} | {:?}",
+            value,
+            input
+        );
+        assert_eq!(
+            *expected,
+            {
+                let mut value = value;
+                value |= *input;
+                value
+            }
+            .bits(),
+            "{:?} |= {:?}",
+            value,
+            input,
+        );
+    }
+}
diff --git a/src/traits.rs b/src/traits.rs
index f8fc757..2823514 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -1,60 +1,164 @@
-use core::{fmt, ops::{BitAnd, BitOr, BitXor, Not}};
+use core::{
+    fmt,
+    ops::{BitAnd, BitOr, BitXor, Not},
+};
 
-use crate::{parser::{ParseError, ParseHex, WriteHex}, iter};
+use crate::{
+    iter,
+    parser::{ParseError, ParseHex, WriteHex},
+};
 
-/// Metadata for an individual flag.
+/**
+A defined flags value that may be named or unnamed.
+*/
 pub struct Flag<B> {
     name: &'static str,
     value: B,
 }
 
 impl<B> Flag<B> {
-    /// Create a new flag with the given name and value.
+    /**
+    Define a flag.
+
+    If `name` is non-empty then the flag is named, otherwise it's unnamed.
+    */
     pub const fn new(name: &'static str, value: B) -> Self {
         Flag { name, value }
     }
 
-    /// Get the name of this flag.
+    /**
+    Get the name of this flag.
+
+    If the flag is unnamed then the returned string will be empty.
+    */
     pub const fn name(&self) -> &'static str {
         self.name
     }
 
-    /// Get the value of this flag.
+    /**
+    Get the flags value of this flag.
+    */
     pub const fn value(&self) -> &B {
         &self.value
     }
+
+    /**
+    Whether the flag is named.
+
+    If [`Flag::name`] returns a non-empty string then this method will return `true`.
+    */
+    pub const fn is_named(&self) -> bool {
+        !self.name.is_empty()
+    }
+
+    /**
+    Whether the flag is unnamed.
+
+    If [`Flag::name`] returns a non-empty string then this method will return `false`.
+    */
+    pub const fn is_unnamed(&self) -> bool {
+        self.name.is_empty()
+    }
 }
 
-/// A set of flags.
-///
-/// This trait is automatically implemented for flags types defined using the `bitflags!` macro.
-/// It can also be implemented manually for custom flags types.
+/**
+A set of defined flags using a bits type as storage.
+
+## Implementing `Flags`
+
+This trait is implemented by the [`bitflags`](macro.bitflags.html) macro:
+
+```
+use bitflags::bitflags;
+
+bitflags! {
+    struct MyFlags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+    }
+}
+```
+
+It can also be implemented manually:
+
+```
+use bitflags::{Flag, Flags};
+
+struct MyFlags(u8);
+
+impl Flags for MyFlags {
+    const FLAGS: &'static [Flag<Self>] = &[
+        Flag::new("A", MyFlags(1)),
+        Flag::new("B", MyFlags(1 << 1)),
+    ];
+
+    type Bits = u8;
+
+    fn from_bits_retain(bits: Self::Bits) -> Self {
+        MyFlags(bits)
+    }
+
+    fn bits(&self) -> Self::Bits {
+        self.0
+    }
+}
+```
+
+## Using `Flags`
+
+The `Flags` trait can be used generically to work with any flags types. In this example,
+we can count the number of defined named flags:
+
+```
+# use bitflags::{bitflags, Flags};
+fn defined_flags<F: Flags>() -> usize {
+    F::FLAGS.iter().filter(|f| f.is_named()).count()
+}
+
+bitflags! {
+    struct MyFlags: u8 {
+        const A = 1;
+        const B = 1 << 1;
+        const C = 1 << 2;
+
+        const _ = !0;
+    }
+}
+
+assert_eq!(3, defined_flags::<MyFlags>());
+```
+*/
 pub trait Flags: Sized + 'static {
-    /// The set of available flags and their names.
+    /// The set of defined flags.
     const FLAGS: &'static [Flag<Self>];
 
-    /// The underlying storage type.
+    /// The underlying bits type.
     type Bits: Bits;
 
-    /// Returns an empty set of flags.
+    /// Get a flags value with all bits unset.
     fn empty() -> Self {
         Self::from_bits_retain(Self::Bits::EMPTY)
     }
 
-    /// Returns the set containing all flags.
+    /// Get a flags value with all known bits set.
     fn all() -> Self {
-        Self::from_bits_truncate(Self::Bits::ALL)
+        let mut truncated = Self::Bits::EMPTY;
+
+        for flag in Self::FLAGS.iter() {
+            truncated = truncated | flag.value().bits();
+        }
+
+        Self::from_bits_retain(truncated)
     }
 
-    /// Returns the raw value of the flags currently stored.
+    /// Get the underlying bits value.
+    ///
+    /// The returned value is exactly the bits set in this flags value.
     fn bits(&self) -> Self::Bits;
 
-    /// Convert from underlying bit representation, unless that
-    /// representation contains bits that do not correspond to a flag.
+    /// Convert from a bits value.
     ///
-    /// Note that each [multi-bit flag] is treated as a unit for this comparison.
-    ///
-    /// [multi-bit flag]: index.html#multi-bit-flags
+    /// This method will return `None` if any unknown bits are set.
     fn from_bits(bits: Self::Bits) -> Option<Self> {
         let truncated = Self::from_bits_truncate(bits);
 
@@ -65,68 +169,62 @@
         }
     }
 
-    /// Convert from underlying bit representation, dropping any bits
-    /// that do not correspond to flags.
-    ///
-    /// Note that each [multi-bit flag] is treated as a unit for this comparison.
-    ///
-    /// [multi-bit flag]: index.html#multi-bit-flags
+    /// Convert from a bits value, unsetting any unknown bits.
     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)
+        Self::from_bits_retain(bits & Self::all().bits())
     }
 
-    /// Convert from underlying bit representation, preserving all
-    /// bits (even those not corresponding to a defined flag).
+    /// Convert from a bits value exactly.
     fn from_bits_retain(bits: Self::Bits) -> Self;
 
-    /// Get the flag for a particular name.
+    /// Get a flags value with the bits of a flag with the given name set.
+    ///
+    /// This method will return `None` if `name` is empty or doesn't
+    /// correspond to any named flag.
     fn from_name(name: &str) -> Option<Self> {
+        // Don't parse empty names as empty flags
+        if name.is_empty() {
+            return None;
+        }
+
         for flag in Self::FLAGS {
             if flag.name() == name {
-                return Some(Self::from_bits_retain(flag.value().bits()))
+                return Some(Self::from_bits_retain(flag.value().bits()));
             }
         }
 
         None
     }
 
-    /// Iterate over enabled flag values.
+    /// Yield a set of contained flags values.
+    ///
+    /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
+    /// will be yielded together as a final flags value.
     fn iter(&self) -> iter::Iter<Self> {
         iter::Iter::new(self)
     }
 
-    /// Iterate over the raw names and bits for enabled flag values.
+    /// Yield a set of contained named flags values.
+    ///
+    /// This method is like [`Flags::iter`], except only yields bits in contained named flags.
+    /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
     fn iter_names(&self) -> iter::IterNames<Self> {
         iter::IterNames::new(self)
     }
 
-    /// Returns `true` if no flags are currently stored.
+    /// Whether all bits in this flags value are unset.
     fn is_empty(&self) -> bool {
         self.bits() == Self::Bits::EMPTY
     }
 
-    /// Returns `true` if all flags are currently set.
+    /// Whether all known bits in this flags value are set.
     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`.
+    /// Whether any set bits in a source flags value are also set in a target flags value.
     fn intersects(&self, other: Self) -> bool
     where
         Self: Sized,
@@ -134,7 +232,7 @@
         self.bits() & other.bits() != Self::Bits::EMPTY
     }
 
-    /// Returns `true` if all of the flags in `other` are contained within `self`.
+    /// Whether all set bits in a source flags value are also set in a target flags value.
     fn contains(&self, other: Self) -> bool
     where
         Self: Sized,
@@ -142,31 +240,34 @@
         self.bits() & other.bits() == other.bits()
     }
 
-    /// Inserts the specified flags in-place.
+    /// The bitwise or (`|`) of the bits in two flags values.
     fn insert(&mut self, other: Self)
     where
         Self: Sized,
     {
-        *self = Self::from_bits_retain(self.bits() | other.bits());
+        *self = Self::from_bits_retain(self.bits()).union(other);
     }
 
-    /// Removes the specified flags in-place.
+    /// The intersection of a source flags value with the complement of a target flags value (`&!`).
+    ///
+    /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
+    /// `remove` won't truncate `other`, but the `!` operator will.
     fn remove(&mut self, other: Self)
     where
         Self: Sized,
     {
-        *self = Self::from_bits_retain(self.bits() & !other.bits());
+        *self = Self::from_bits_retain(self.bits()).difference(other);
     }
 
-    /// Toggles the specified flags in-place.
+    /// The bitwise exclusive-or (`^`) of the bits in two flags values.
     fn toggle(&mut self, other: Self)
     where
         Self: Sized,
     {
-        *self = Self::from_bits_retain(self.bits() ^ other.bits());
+        *self = Self::from_bits_retain(self.bits()).symmetric_difference(other);
     }
 
-    /// Inserts or removes the specified flags depending on the passed value.
+    /// Call [`Flags::insert`] when `value` is `true` or [`Flags::remove`] when `value` is `false`.
     fn set(&mut self, other: Self, value: bool)
     where
         Self: Sized,
@@ -178,64 +279,43 @@
         }
     }
 
-    /// 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`.
+    /// The bitwise and (`&`) of the bits in two flags values.
     #[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).
+    /// The bitwise or (`|`) of the bits in two flags values.
     #[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`.
+    /// The intersection of a source flags value with the complement of a target flags value (`&!`).
     ///
-    /// 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 method is not equivalent to `self & !other` when `other` has unknown bits set.
+    /// `difference` won't truncate `other`, but the `!` operator will.
     #[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
+    /// The bitwise exclusive-or (`^`) of the bits in two flags values.
     #[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.
+    /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
     #[must_use]
     fn complement(self) -> Self {
         Self::from_bits_truncate(!self.bits())
     }
 }
 
-/// Underlying storage for a flags type.
+/**
+A bits type that can be used as storage for a flags type.
+*/
 pub trait Bits:
     Clone
     + Copy
@@ -247,10 +327,10 @@
     + Sized
     + 'static
 {
-    /// The value of `Self` where no bits are set.
+    /// A value with all bits unset.
     const EMPTY: Self;
 
-    /// The value of `Self` where all bits are set.
+    /// A value with all bits set.
     const ALL: Self;
 }
 
@@ -320,6 +400,7 @@
     type Internal;
 }
 
+#[doc(hidden)]
 #[deprecated(note = "use the `Flags` trait instead")]
 pub trait BitFlags: ImplementedByBitFlagsMacro + Flags {
     /// An iterator over enabled flags in an instance of the type.