Repository: bitflags/bitflags
Pull request #250 (2021-08-05 01:36:24)

Prepare for 1.3.0 release
[Changeset since the last release](https://github.com/bitflags/bitflags/compare/1.2.1...master)

This includes over a year's worth of modernization and cleanups. The biggest external changes are the inclusion of new constant set operators to better support bitflags in const contexts (#244) and better support for multiple and empty `bitflags!` invocations (#235 and #225)


Patch:
diff --git a/.gitignore b/.gitignore
index fbd9642..61c3331 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+wip
 target
 Cargo.lock
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d49101..91fd4bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,48 @@
+# 1.3.0
+
+- Add `#[repr(transparent)]` ([#187])
+
+- End `empty` doc comment with full stop ([#202])
+
+- Fix typo in crate root docs ([#206])
+
+- Document from_bits_unchecked unsafety ([#207])
+
+- Let `is_all` ignore extra bits ([#211])
+
+- Allows empty flag definition ([#225])
+
+- Making crate accessible from std ([#227])
+
+- Make `from_bits` a const fn ([#229])
+
+- Allow multiple bitflags structs in one macro invocation ([#235])
+
+- Add named functions to perform set operations ([#244])
+
+- Fix typos in method docs ([#245])
+
+- Modernization of the `bitflags` macro to take advantage of newer features and 2018 idioms ([#246])
+
+- Fix regression (in an unreleased feature) and simplify tests ([#247])
+
+- Use `Self` and fix bug when overriding `stringify!` ([#249])
+
+[#187]: https://github.com/bitflags/bitflags/pull/187
+[#202]: https://github.com/bitflags/bitflags/pull/202
+[#206]: https://github.com/bitflags/bitflags/pull/206
+[#207]: https://github.com/bitflags/bitflags/pull/207
+[#211]: https://github.com/bitflags/bitflags/pull/211
+[#225]: https://github.com/bitflags/bitflags/pull/225
+[#227]: https://github.com/bitflags/bitflags/pull/227
+[#229]: https://github.com/bitflags/bitflags/pull/229
+[#235]: https://github.com/bitflags/bitflags/pull/235
+[#244]: https://github.com/bitflags/bitflags/pull/244
+[#245]: https://github.com/bitflags/bitflags/pull/245
+[#246]: https://github.com/bitflags/bitflags/pull/246
+[#247]: https://github.com/bitflags/bitflags/pull/247
+[#249]: https://github.com/bitflags/bitflags/pull/249
+
 # 1.2.1
 
 - Remove extraneous `#[inline]` attributes ([#194])
diff --git a/Cargo.toml b/Cargo.toml
index 44d0f19..45914ef 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "bitflags"
 # NB: When modifying, also modify:
 #   1. html_root_url in lib.rs
 #   2. number in readme (for breaking changes)
-version = "1.2.1"
+version = "1.3.0"
 edition = "2018"
 authors = ["The Rust Project Developers"]
 license = "MIT/Apache-2.0"
@@ -24,6 +24,7 @@ compiler_builtins = { version = '0.1.2', optional = true }
 
 [dev-dependencies]
 trybuild = "1.0"
+rustversion = "1.0"
 serde = "1.0"
 serde_derive = "1.0"
 serde_json = "1.0"
diff --git a/README.md b/README.md
index 005a0a4..0da0f85 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-bitflags = "1.2"
+bitflags = "1.3"
 ```
 
 and this to your source code:
diff --git a/src/lib.rs b/src/lib.rs
index 6f58a42..f54b712 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -254,9 +254,11 @@
 //!     assert!(none.is_empty());
 //! }
 //! ```
+//!
+//! Users should generally avoid defining a flag with a value of zero.
 
 #![cfg_attr(not(test), no_std)]
-#![doc(html_root_url = "https://docs.rs/bitflags/1.2.1")]
+#![doc(html_root_url = "https://docs.rs/bitflags/1.3.0")]
 
 #[doc(hidden)]
 pub extern crate core as _core;
@@ -1203,7 +1205,7 @@ mod tests {
     #[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), which is enoug
+        // (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);


Test patch:
diff --git a/tests/compile-fail/.gitignore b/tests/compile-fail/.gitignore
new file mode 100644
index 0000000..4dd9abc
--- /dev/null
+++ b/tests/compile-fail/.gitignore
@@ -0,0 +1,1 @@
+*.stderr
diff --git a/tests/compile-fail/private_flags.stderr.beta b/tests/compile-fail/private_flags.stderr.beta
new file mode 100644
index 0000000..d23f832
--- /dev/null
+++ b/tests/compile-fail/private_flags.stderr.beta
@@ -0,0 +1,18 @@
+error[E0603]: struct `Flags2` is private
+  --> $DIR/private_flags.rs:17:26
+   |
+17 |     let flag2 = example::Flags2::FLAG_B;
+   |                          ^^^^^^ private struct
+   |
+note: the struct `Flags2` is defined here
+  --> $DIR/private_flags.rs:4:5
+   |
+4  | /     bitflags! {
+5  | |         pub struct Flags1: u32 {
+6  | |             const FLAG_A = 0b00000001;
+7  | |         }
+...  |
+11 | |         }
+12 | |     }
+   | |_____^
+   = note: this error originates in the macro `bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index db50dfd..ae0c9df 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -1,5 +1,55 @@
+use std::{
+    fs,
+    ffi::OsStr,
+    io,
+    path::Path,
+};
+
 #[test]
 fn compile_fail() {
+    prepare_stderr_files("tests/compile-fail").unwrap();
+
     let t = trybuild::TestCases::new();
     t.compile_fail("tests/compile-fail/*.rs");
 }
+
+// Compiler messages may change between versions
+// We don't want to have to track these too closely for `bitflags`, but
+// having some message to check makes sure user-facing errors are sensical.
+// 
+// The approach we use is to run the test on all compilers, but only check stderr
+// output on beta (which is the next stable release). We do this by default ignoring
+// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files
+// when we happen to be running on a beta compiler.
+fn prepare_stderr_files(path: impl AsRef<Path>) -> io::Result<()> {
+    for entry in fs::read_dir(path)? {
+        let entry = entry?;
+
+        if entry.path().extension().and_then(OsStr::to_str) == Some("beta") {
+            let renamed = entry.path().with_extension("");
+
+            // Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta`
+            // file if it exists. On `beta` compilers, we'll recreate it. On other compilers,
+            // we don't want to end up checking it anyways.
+            if renamed.exists() {
+                fs::remove_file(&renamed)?;
+            }
+
+            rename_beta_stderr(entry.path(), renamed)?;
+        }
+    }
+
+    Ok(())
+}
+
+#[rustversion::beta]
+fn rename_beta_stderr(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
+    fs::copy(from, to)?;
+
+    Ok(())
+}
+
+#[rustversion::not(beta)]
+fn rename_beta_stderr(_: impl AsRef<Path>, _: impl AsRef<Path>) -> io::Result<()> {
+    Ok(())
+}