From 302ed9ebe2ed573cfde66a93a385c6a84994ef9b Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:01:45 +1000 Subject: [PATCH 1/8] add more platform coverage to CI --- .github/workflows/rust.yml | 57 +++++++++++++++--------- Cargo.toml | 1 - bors.toml | 3 -- src/lib.rs | 74 ++++++++++++++++---------------- tests/compile-pass/no_prelude.rs | 13 ++++++ 5 files changed, 85 insertions(+), 63 deletions(-) delete mode 100644 bors.toml create mode 100644 tests/compile-pass/no_prelude.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ffe0edad..41f0b72c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -7,32 +7,47 @@ env: jobs: check: - name: Test - runs-on: ubuntu-latest + name: "Tests / OS: ${{ matrix.os }} - ${{ matrix.channel }}-${{ matrix.rust_target }}" + runs-on: ${{ matrix.os }} strategy: - fail-fast: true matrix: - rust: - - stable - - beta - - nightly - - 1.46.0 + exclude: + - os: macos-10.15 + rust_target: x86_64-gnu + - os: macos-10.15 + rust_target: x86_64-msvc + - os: windows-2019 + rust_target: x86_64-apple-darwin + - os: ubuntu-20.04 + rust_target: x86_64-msvc + - os: ubuntu-20.04 + rust_target: x86_64-apple-darwin + channel: + - stable + - beta + - nightly + os: + - macos-10.15 + - windows-2019 + - ubuntu-20.04 + rust_target: + - x86_64-gnu + - x86_64-msvc + - x86_64-apple-darwin + steps: - - name: Checkout sources - uses: actions/checkout@v2 + - name: Checkout repository + uses: actions/checkout@v2 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + override: true + profile: minimal + toolchain: ${{ matrix.channel }}-${{ matrix.rust_target }} - - name: Default features - uses: actions-rs/cargo@v1 - with: - command: test - args: --features example_generated + - name: Tests + run: cargo test --all-features embedded: name: Build (embedded) diff --git a/Cargo.toml b/Cargo.toml index 4476122a..92236aa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ serde_derive = "1.0" serde_json = "1.0" [features] -default = [] example_generated = [] rustc-dep-of-std = ["core", "compiler_builtins"] diff --git a/bors.toml b/bors.toml deleted file mode 100644 index 867e8a51..00000000 --- a/bors.toml +++ /dev/null @@ -1,3 +0,0 @@ -status = [ - "rust", -] diff --git a/src/lib.rs b/src/lib.rs index b9d77f7c..a66fb4a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -278,9 +278,6 @@ #![cfg_attr(not(test), no_std)] #![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")] -#[doc(hidden)] -pub extern crate core as _core; - #[doc(inline)] pub use bitflags_trait::BitFlags; @@ -288,6 +285,7 @@ mod bitflags_trait; #[doc(hidden)] pub mod __private { + pub use core; pub use crate::bitflags_trait::ImplementedByBitFlagsMacro; } @@ -440,8 +438,8 @@ macro_rules! __impl_bitflags { )* } ) => { - impl $crate::_core::fmt::Debug for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { + impl $crate::__private::core::fmt::Debug for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { // This convoluted approach is to handle #[cfg]-based flag // omission correctly. For example it needs to support: // @@ -485,7 +483,7 @@ macro_rules! __impl_bitflags { f.write_str(" | ")?; } first = false; - f.write_str($crate::_core::stringify!($Flag))?; + f.write_str($crate::__private::core::stringify!($Flag))?; } )* let extra_bits = self.bits & !Self::all().bits(); @@ -494,32 +492,32 @@ macro_rules! __impl_bitflags { f.write_str(" | ")?; } first = false; - $crate::_core::write!(f, "{:#x}", extra_bits)?; + $crate::__private::core::write!(f, "{:#x}", extra_bits)?; } if first { f.write_str("(empty)")?; } - $crate::_core::fmt::Result::Ok(()) + $crate::__private::core::fmt::Result::Ok(()) } } - impl $crate::_core::fmt::Binary for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::Binary::fmt(&self.bits, f) + impl $crate::__private::core::fmt::Binary for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::Binary::fmt(&self.bits, f) } } - impl $crate::_core::fmt::Octal for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::Octal::fmt(&self.bits, f) + impl $crate::__private::core::fmt::Octal for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::Octal::fmt(&self.bits, f) } } - impl $crate::_core::fmt::LowerHex for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::LowerHex::fmt(&self.bits, f) + impl $crate::__private::core::fmt::LowerHex for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::LowerHex::fmt(&self.bits, f) } } - impl $crate::_core::fmt::UpperHex for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { - $crate::_core::fmt::UpperHex::fmt(&self.bits, f) + impl $crate::__private::core::fmt::UpperHex for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + $crate::__private::core::fmt::UpperHex::fmt(&self.bits, f) } } @@ -558,7 +556,7 @@ macro_rules! __impl_bitflags { /// Convert from underlying bit representation, unless that /// representation contains bits that do not correspond to a flag. #[inline] - pub const fn from_bits(bits: $T) -> $crate::_core::option::Option { + pub const fn from_bits(bits: $T) -> $crate::__private::core::option::Option { let truncated = Self::from_bits_truncate(bits).bits; if truncated == bits { Some(Self{ bits }) @@ -771,7 +769,7 @@ macro_rules! __impl_bitflags { ]; let mut start = 0; - $crate::_core::iter::from_fn(move || { + $crate::__private::core::iter::from_fn(move || { if self.is_empty() || NUM_FLAGS == 0 { None }else{ @@ -815,12 +813,12 @@ macro_rules! __impl_bitflags { const OPTIONS_NAMES: [&'static str; NUM_FLAGS] = [ $( $(#[$attr $($args)*])* - $crate::_core::stringify!($Flag), + $crate::__private::core::stringify!($Flag), )* ]; let mut start = 0; - $crate::_core::iter::from_fn(move || { + $crate::__private::core::iter::from_fn(move || { if self.is_empty() || NUM_FLAGS == 0 { None }else{ @@ -841,7 +839,7 @@ macro_rules! __impl_bitflags { } - impl $crate::_core::ops::BitOr for $BitFlags { + impl $crate::__private::core::ops::BitOr for $BitFlags { type Output = Self; /// Returns the union of the two sets of flags. @@ -851,7 +849,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::BitOrAssign for $BitFlags { + impl $crate::__private::core::ops::BitOrAssign for $BitFlags { /// Adds the set of flags. #[inline] fn bitor_assign(&mut self, other: Self) { @@ -859,7 +857,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::BitXor for $BitFlags { + impl $crate::__private::core::ops::BitXor for $BitFlags { type Output = Self; /// Returns the left flags, but with all the right flags toggled. @@ -869,7 +867,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::BitXorAssign for $BitFlags { + impl $crate::__private::core::ops::BitXorAssign for $BitFlags { /// Toggles the set of flags. #[inline] fn bitxor_assign(&mut self, other: Self) { @@ -877,7 +875,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::BitAnd for $BitFlags { + impl $crate::__private::core::ops::BitAnd for $BitFlags { type Output = Self; /// Returns the intersection between the two sets of flags. @@ -887,7 +885,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::BitAndAssign for $BitFlags { + impl $crate::__private::core::ops::BitAndAssign for $BitFlags { /// Disables all flags disabled in the set. #[inline] fn bitand_assign(&mut self, other: Self) { @@ -895,7 +893,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::Sub for $BitFlags { + impl $crate::__private::core::ops::Sub for $BitFlags { type Output = Self; /// Returns the set difference of the two sets of flags. @@ -905,7 +903,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::SubAssign for $BitFlags { + impl $crate::__private::core::ops::SubAssign for $BitFlags { /// Disables all flags enabled in the set. #[inline] fn sub_assign(&mut self, other: Self) { @@ -913,7 +911,7 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::ops::Not for $BitFlags { + impl $crate::__private::core::ops::Not for $BitFlags { type Output = Self; /// Returns the complement of this set of flags. @@ -923,16 +921,16 @@ macro_rules! __impl_bitflags { } } - impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { - fn extend>(&mut self, iterator: T) { + impl $crate::__private::core::iter::Extend<$BitFlags> for $BitFlags { + fn extend>(&mut self, iterator: T) { for item in iterator { self.insert(item) } } } - impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { - fn from_iter>(iterator: T) -> Self { + impl $crate::__private::core::iter::FromIterator<$BitFlags> for $BitFlags { + fn from_iter>(iterator: T) -> Self { let mut result = Self::empty(); result.extend(iterator); result @@ -954,7 +952,7 @@ macro_rules! __impl_bitflags { $BitFlags::bits(self) } - fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { + fn from_bits(bits: $T) -> $crate::__private::core::option::Option<$BitFlags> { $BitFlags::from_bits(bits) } diff --git a/tests/compile-pass/no_prelude.rs b/tests/compile-pass/no_prelude.rs new file mode 100644 index 00000000..b6932967 --- /dev/null +++ b/tests/compile-pass/no_prelude.rs @@ -0,0 +1,13 @@ +#![no_std] +#![no_implicit_prelude] + +bitflags::bitflags! { + pub struct Flags: u32 { + const A = 0b00000001; + const B = 0b00000010; + const C = 0b00000100; + const ABC = Flags::A.bits | Flags::B.bits | Flags::C.bits; + } +} + +fn main() {} From deb1ecf00998dd0f0727c7b68542c073aa95adfe Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:06:10 +1000 Subject: [PATCH 2/8] don't test with all_features --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 41f0b72c..b7b2486e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -47,7 +47,7 @@ jobs: toolchain: ${{ matrix.channel }}-${{ matrix.rust_target }} - name: Tests - run: cargo test --all-features + run: cargo test --features example_generated embedded: name: Build (embedded) From b2ff750f10460a41485a83cdafbf74edaa55db65 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:12:14 +1000 Subject: [PATCH 3/8] std main --- tests/compile-pass/no_prelude.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/compile-pass/no_prelude.rs b/tests/compile-pass/no_prelude.rs index b6932967..c06c1d13 100644 --- a/tests/compile-pass/no_prelude.rs +++ b/tests/compile-pass/no_prelude.rs @@ -1,4 +1,3 @@ -#![no_std] #![no_implicit_prelude] bitflags::bitflags! { From 094f69e5adcd1e88124123ff94df2732ef9ce9d9 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:16:57 +1000 Subject: [PATCH 4/8] fix up iterator tests --- src/lib.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a66fb4a0..99bcabe2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -405,6 +405,7 @@ macro_rules! __impl_all_bitflags { #[allow(non_snake_case)] trait __BitFlags { $( + #[allow(deprecated)] const $Flag: $T = 0; )+ } @@ -1950,13 +1951,34 @@ mod tests { } } + let count = { + #[cfg(any(unix, windows))] + { + 4 + } + + #[cfg(not(any(unix, windows)))] + { + 3 + } + }; + let flags = Flags::all(); - assert_eq!(flags.iter().count(), 4); + assert_eq!(flags.iter().count(), count); let mut iter = flags.iter(); assert_eq!(iter.next().unwrap(), Flags::ONE); assert_eq!(iter.next().unwrap(), Flags::TWO); assert_eq!(iter.next().unwrap(), Flags::THREE); - assert_eq!(iter.next().unwrap(), Flags::FOUR_UNIX); + + #[cfg(unix)] + { + assert_eq!(iter.next().unwrap(), Flags::FOUR_UNIX); + } + #[cfg(windows)] + { + assert_eq!(iter.next().unwrap(), Flags::FOUR_WIN); + } + assert_eq!(iter.next(), None); let flags = Flags::empty(); From fb94374b0ab82e07b3c7ae1a43294dc5335ba5fb Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:19:05 +1000 Subject: [PATCH 5/8] need to extern bitflags without a prelude --- tests/compile-pass/no_prelude.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/compile-pass/no_prelude.rs b/tests/compile-pass/no_prelude.rs index c06c1d13..c54b7a31 100644 --- a/tests/compile-pass/no_prelude.rs +++ b/tests/compile-pass/no_prelude.rs @@ -1,5 +1,7 @@ #![no_implicit_prelude] +extern crate bitflags; + bitflags::bitflags! { pub struct Flags: u32 { const A = 0b00000001; From efa93b154568856714d7221eb46da73ccb4ed121 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 09:48:32 +1000 Subject: [PATCH 6/8] fix up imports and use iter for Debug format --- src/lib.rs | 145 +++++++++++++++-------------------------------------- 1 file changed, 40 insertions(+), 105 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 99bcabe2..d6d30f51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -441,53 +441,20 @@ macro_rules! __impl_bitflags { ) => { impl $crate::__private::core::fmt::Debug for $BitFlags { fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { - // This convoluted approach is to handle #[cfg]-based flag - // omission correctly. For example it needs to support: - // - // #[cfg(unix)] const A: Flag = /* ... */; - // #[cfg(windows)] const B: Flag = /* ... */; - - // Unconditionally define a check for every flag, even disabled - // ones. - #[allow(non_snake_case)] - trait __BitFlags { - $( - #[inline] - fn $Flag(&self) -> bool { false } - )* - } + // Iterate over the valid flags + let mut first = true; + for (name, _) in self.iter() { + if !first { + f.write_str(" | ")?; + } - // Conditionally override the check for just those flags that - // are not #[cfg]ed away. - #[allow(non_snake_case)] - impl __BitFlags for $BitFlags { - $( - __impl_bitflags! { - #[allow(deprecated)] - #[inline] - $(? #[$attr $($args)*])* - fn $Flag(&self) -> bool { - if Self::$Flag.bits == 0 && self.bits != 0 { - false - } else { - self.bits & Self::$Flag.bits == Self::$Flag.bits - } - } - } - )* + first = false; + f.write_str(name)?; } - let mut first = true; - $( - if ::$Flag(self) { - if !first { - f.write_str(" | ")?; - } - first = false; - f.write_str($crate::__private::core::stringify!($Flag))?; - } - )* + // Append any extra bits that correspond to flags to the end of the format let extra_bits = self.bits & !Self::all().bits(); + if extra_bits != 0 { if !first { f.write_str(" | ")?; @@ -495,27 +462,33 @@ macro_rules! __impl_bitflags { first = false; $crate::__private::core::write!(f, "{:#x}", extra_bits)?; } + if first { f.write_str("(empty)")?; } + $crate::__private::core::fmt::Result::Ok(()) } } + impl $crate::__private::core::fmt::Binary for $BitFlags { fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { $crate::__private::core::fmt::Binary::fmt(&self.bits, f) } } + impl $crate::__private::core::fmt::Octal for $BitFlags { fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { $crate::__private::core::fmt::Octal::fmt(&self.bits, f) } } + impl $crate::__private::core::fmt::LowerHex for $BitFlags { fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { $crate::__private::core::fmt::LowerHex::fmt(&self.bits, f) } } + impl $crate::__private::core::fmt::UpperHex for $BitFlags { fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { $crate::__private::core::fmt::UpperHex::fmt(&self.bits, f) @@ -560,9 +533,9 @@ macro_rules! __impl_bitflags { pub const fn from_bits(bits: $T) -> $crate::__private::core::option::Option { let truncated = Self::from_bits_truncate(bits).bits; if truncated == bits { - Some(Self{ bits }) + $crate::__private::core::option::Option::Some(Self{ bits }) } else { - None + $crate::__private::core::option::Option::None } } @@ -571,7 +544,7 @@ macro_rules! __impl_bitflags { #[inline] pub const fn from_bits_truncate(bits: $T) -> Self { if bits == 0 { - return Self{ bits } + return Self { bits } } #[allow(unused_mut)] @@ -745,8 +718,8 @@ macro_rules! __impl_bitflags { Self::from_bits_truncate(!self.bits) } - /// Returns an iterator over all the flags in this set. - pub fn iter(mut self) -> impl Iterator { + /// Returns an iterator over set flags and their names. + pub fn iter(mut self) -> impl $crate::__private::core::iter::Iterator { const NUM_FLAGS: usize = { #[allow(unused_mut)] let mut num_flags = 0; @@ -761,48 +734,7 @@ macro_rules! __impl_bitflags { num_flags }; - const OPTIONS: [$BitFlags; NUM_FLAGS] = [ - $( - #[allow(unused_doc_comments, unused_attributes)] - $(#[$attr $($args)*])* - $BitFlags::$Flag, - )* - ]; - let mut start = 0; - - $crate::__private::core::iter::from_fn(move || { - if self.is_empty() || NUM_FLAGS == 0 { - None - }else{ - for flag in OPTIONS[start..NUM_FLAGS].iter().copied() { - start += 1; - if self.contains(flag) { - self.remove(flag); - return Some(flag) - } - } - - None - } - }) - } - /// Returns an iterator over all the flags names as &'static str in this set. - pub fn iter_names(mut self) -> impl Iterator { - const NUM_FLAGS: usize = { - #[allow(unused_mut)] - let mut num_flags = 0; - - $( - #[allow(unused_doc_comments, unused_attributes)] - $(#[$attr $($args)*])* - { - num_flags += 1; - } - )* - - num_flags - }; const OPTIONS: [$BitFlags; NUM_FLAGS] = [ $( #[allow(unused_doc_comments, unused_attributes)] @@ -810,6 +742,7 @@ macro_rules! __impl_bitflags { $BitFlags::$Flag, )* ]; + #[allow(unused_doc_comments, unused_attributes)] const OPTIONS_NAMES: [&'static str; NUM_FLAGS] = [ $( @@ -817,23 +750,25 @@ macro_rules! __impl_bitflags { $crate::__private::core::stringify!($Flag), )* ]; + let mut start = 0; $crate::__private::core::iter::from_fn(move || { if self.is_empty() || NUM_FLAGS == 0 { - None - }else{ + $crate::__private::core::option::Option::None + } else { for (flag, flag_name) in OPTIONS[start..NUM_FLAGS].iter().copied() .zip(OPTIONS_NAMES[start..NUM_FLAGS].iter().copied()) { start += 1; if self.contains(flag) { self.remove(flag); - return Some(flag_name) + + return $crate::__private::core::option::Option::Some((flag_name, flag)) } } - None + $crate::__private::core::option::Option::None } }) } @@ -1669,14 +1604,14 @@ mod tests { fn test_debug() { assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); - assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); + assert_eq!(format!("{:?}", Flags::ABC), "A | B | C"); let extra = unsafe { Flags::from_bits_unchecked(0xb8) }; assert_eq!(format!("{:?}", extra), "0xb8"); assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8"); assert_eq!( format!("{:?}", Flags::ABC | extra), - "A | B | C | ABC | 0xb8" + "A | B | C | 0xb8" ); assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)"); @@ -1835,8 +1770,8 @@ mod tests { assert!(Flags::SOME.contains(Flags::NONE)); assert!(Flags::NONE.is_empty()); - assert_eq!(format!("{:?}", Flags::empty()), "NONE"); - assert_eq!(format!("{:?}", Flags::SOME), "SOME"); + assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); + assert_eq!(format!("{:?}", Flags::SOME), "NONE | SOME"); } #[test] @@ -1866,7 +1801,7 @@ mod tests { assert_eq!(format!("{:?}", Flags128::A), "A"); assert_eq!(format!("{:?}", Flags128::B), "B"); assert_eq!(format!("{:?}", Flags128::C), "C"); - assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC"); + assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C"); } #[test] @@ -1966,17 +1901,17 @@ mod tests { let flags = Flags::all(); assert_eq!(flags.iter().count(), count); let mut iter = flags.iter(); - assert_eq!(iter.next().unwrap(), Flags::ONE); - assert_eq!(iter.next().unwrap(), Flags::TWO); - assert_eq!(iter.next().unwrap(), Flags::THREE); + 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(), Flags::FOUR_UNIX); + assert_eq!(iter.next().unwrap(), ("FOUR_UNIX", Flags::FOUR_UNIX)); } #[cfg(windows)] { - assert_eq!(iter.next().unwrap(), Flags::FOUR_WIN); + assert_eq!(iter.next().unwrap(), ("FOUR_WIN", Flags::FOUR_WIN)); } assert_eq!(iter.next(), None); @@ -1987,8 +1922,8 @@ mod tests { let flags = Flags::ONE | Flags::THREE; assert_eq!(flags.iter().count(), 2); let mut iter = flags.iter(); - assert_eq!(iter.next().unwrap(), Flags::ONE); - assert_eq!(iter.next().unwrap(), Flags::THREE); + assert_eq!(iter.next().unwrap(), ("ONE", Flags::ONE)); + assert_eq!(iter.next().unwrap(), ("THREE", Flags::THREE)); assert_eq!(iter.next(), None); } } From fd0accee3fb67c08ce3879d5a410c0b7fc46c37e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 10:05:43 +1000 Subject: [PATCH 7/8] update beta messages --- src/lib.rs | 4 ++ tests/compile-fail/cfg/multi.stderr.beta | 20 +------ .../non_integer_base/all_defined.stderr.beta | 58 ++++--------------- 3 files changed, 16 insertions(+), 66 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d6d30f51..a2d3193b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -720,6 +720,8 @@ macro_rules! __impl_bitflags { /// Returns an iterator over set flags and their names. pub fn iter(mut self) -> impl $crate::__private::core::iter::Iterator { + use $crate::__private::core::iter::Iterator as _; + const NUM_FLAGS: usize = { #[allow(unused_mut)] let mut num_flags = 0; @@ -867,6 +869,8 @@ macro_rules! __impl_bitflags { impl $crate::__private::core::iter::FromIterator<$BitFlags> for $BitFlags { fn from_iter>(iterator: T) -> Self { + use $crate::__private::core::iter::Extend; + let mut result = Self::empty(); result.extend(iterator); result diff --git a/tests/compile-fail/cfg/multi.stderr.beta b/tests/compile-fail/cfg/multi.stderr.beta index 75960547..be9ba21c 100644 --- a/tests/compile-fail/cfg/multi.stderr.beta +++ b/tests/compile-fail/cfg/multi.stderr.beta @@ -1,23 +1,5 @@ error[E0428]: the name `FOO` is defined multiple times - --> $DIR/multi.rs:6:1 - | -6 | / bitflags! { -7 | | pub struct Flags: u32 { -8 | | #[cfg(target_os = "linux")] -9 | | const FOO = 1; -... | -12 | | } -13 | | } - | | ^ - | | | - | |_`FOO` redefined here - | previous definition of the value `FOO` here - | - = note: `FOO` must be defined only once in the value namespace of this trait - = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0428]: the name `FOO` is defined multiple times - --> $DIR/multi.rs:6:1 + --> tests/compile-fail/cfg/multi.rs:6:1 | 6 | / bitflags! { 7 | | pub struct Flags: u32 { diff --git a/tests/compile-fail/non_integer_base/all_defined.stderr.beta b/tests/compile-fail/non_integer_base/all_defined.stderr.beta index 0607f234..fb9c2867 100644 --- a/tests/compile-fail/non_integer_base/all_defined.stderr.beta +++ b/tests/compile-fail/non_integer_base/all_defined.stderr.beta @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -13,11 +13,11 @@ error[E0308]: mismatched types = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) help: try wrapping the expression in `MyInt` | -492 | if extra_bits != MyInt(0) { +458 | if extra_bits != MyInt(0) { | ++++++ + error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -31,11 +31,11 @@ error[E0308]: mismatched types = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) help: try wrapping the expression in `MyInt` | -536 | Self { bits: MyInt(0) } +508 | Self { bits: MyInt(0) } | ++++++ + error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -49,11 +49,11 @@ error[E0308]: mismatched types = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) help: try wrapping the expression in `MyInt` | -574 | if bits == MyInt(0) { +546 | if bits == MyInt(0) { | ++++++ + error[E0277]: no implementation for `{integer} |= MyInt` - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -68,7 +68,7 @@ error[E0277]: no implementation for `{integer} |= MyInt` = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -82,47 +82,11 @@ error[E0308]: mismatched types = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) help: try wrapping the expression in `MyInt` | -589 | Self { bits: MyInt(truncated) } +561 | Self { bits: MyInt(truncated) } | ++++++ + error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 - | -115 | / bitflags! { -116 | | struct Flags128: MyInt { -117 | | const A = MyInt(0b0000_0001u8); -118 | | const B = MyInt(0b0000_0010u8); -119 | | const C = MyInt(0b0000_0100u8); -120 | | } -121 | | } - | |_^ expected struct `MyInt`, found integer - | - = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) -help: try wrapping the expression in `MyInt` - | -471 | if Self::$Flag.bits == MyInt(0) && self.bits != 0 { - | ++++++ + - -error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 - | -115 | / bitflags! { -116 | | struct Flags128: MyInt { -117 | | const A = MyInt(0b0000_0001u8); -118 | | const B = MyInt(0b0000_0010u8); -119 | | const C = MyInt(0b0000_0100u8); -120 | | } -121 | | } - | |_^ expected struct `MyInt`, found integer - | - = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) -help: try wrapping the expression in `MyInt` - | -471 | if Self::$Flag.bits == 0 && self.bits != MyInt(0) { - | ++++++ + - -error[E0308]: mismatched types - --> $DIR/all_defined.rs:115:1 + --> tests/compile-fail/non_integer_base/all_defined.rs:115:1 | 115 | / bitflags! { 116 | | struct Flags128: MyInt { @@ -136,5 +100,5 @@ error[E0308]: mismatched types = note: this error originates in the macro `__impl_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) help: try wrapping the expression in `MyInt` | -410 | const $Flag: $T = MyInt(0); +409 | const $Flag: $T = MyInt(0); | ++++++ + From dcfd6737ac7ec34832f1480183a02777c97f218e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 3 May 2022 12:55:31 +1000 Subject: [PATCH 8/8] work around need for stderr --- Cargo.toml | 1 - tests/compile-fail/.gitignore | 1 - .../cfg/{multi.stderr.beta => multi.stderr} | 0 .../impls/{copy.stderr.beta => copy.stderr} | 0 .../impls/{eq.stderr.beta => eq.stderr} | 0 ...defined.stderr.beta => all_defined.stderr} | 0 ...missing.stderr.beta => all_missing.stderr} | 0 ...om_impl.stderr.beta => custom_impl.stderr} | 0 ...field.stderr.beta => private_field.stderr} | 0 ...flags.stderr.beta => private_flags.stderr} | 0 ...pub_const.stderr.beta => pub_const.stderr} | 0 tests/compile.rs | 104 +----------------- 12 files changed, 6 insertions(+), 100 deletions(-) delete mode 100644 tests/compile-fail/.gitignore rename tests/compile-fail/cfg/{multi.stderr.beta => multi.stderr} (100%) rename tests/compile-fail/impls/{copy.stderr.beta => copy.stderr} (100%) rename tests/compile-fail/impls/{eq.stderr.beta => eq.stderr} (100%) rename tests/compile-fail/non_integer_base/{all_defined.stderr.beta => all_defined.stderr} (100%) rename tests/compile-fail/non_integer_base/{all_missing.stderr.beta => all_missing.stderr} (100%) rename tests/compile-fail/trait/{custom_impl.stderr.beta => custom_impl.stderr} (100%) rename tests/compile-fail/visibility/{private_field.stderr.beta => private_field.stderr} (100%) rename tests/compile-fail/visibility/{private_flags.stderr.beta => private_flags.stderr} (100%) rename tests/compile-fail/visibility/{pub_const.stderr.beta => pub_const.stderr} (100%) diff --git a/Cargo.toml b/Cargo.toml index 92236aa0..9c7c7aa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ compiler_builtins = { version = '0.1.2', optional = true } [dev-dependencies] trybuild = "1.0" rustversion = "1.0" -walkdir = "2.3" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/tests/compile-fail/.gitignore b/tests/compile-fail/.gitignore deleted file mode 100644 index 4dd9abc8..00000000 --- a/tests/compile-fail/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.stderr diff --git a/tests/compile-fail/cfg/multi.stderr.beta b/tests/compile-fail/cfg/multi.stderr similarity index 100% rename from tests/compile-fail/cfg/multi.stderr.beta rename to tests/compile-fail/cfg/multi.stderr diff --git a/tests/compile-fail/impls/copy.stderr.beta b/tests/compile-fail/impls/copy.stderr similarity index 100% rename from tests/compile-fail/impls/copy.stderr.beta rename to tests/compile-fail/impls/copy.stderr diff --git a/tests/compile-fail/impls/eq.stderr.beta b/tests/compile-fail/impls/eq.stderr similarity index 100% rename from tests/compile-fail/impls/eq.stderr.beta rename to tests/compile-fail/impls/eq.stderr diff --git a/tests/compile-fail/non_integer_base/all_defined.stderr.beta b/tests/compile-fail/non_integer_base/all_defined.stderr similarity index 100% rename from tests/compile-fail/non_integer_base/all_defined.stderr.beta rename to tests/compile-fail/non_integer_base/all_defined.stderr diff --git a/tests/compile-fail/non_integer_base/all_missing.stderr.beta b/tests/compile-fail/non_integer_base/all_missing.stderr similarity index 100% rename from tests/compile-fail/non_integer_base/all_missing.stderr.beta rename to tests/compile-fail/non_integer_base/all_missing.stderr diff --git a/tests/compile-fail/trait/custom_impl.stderr.beta b/tests/compile-fail/trait/custom_impl.stderr similarity index 100% rename from tests/compile-fail/trait/custom_impl.stderr.beta rename to tests/compile-fail/trait/custom_impl.stderr diff --git a/tests/compile-fail/visibility/private_field.stderr.beta b/tests/compile-fail/visibility/private_field.stderr similarity index 100% rename from tests/compile-fail/visibility/private_field.stderr.beta rename to tests/compile-fail/visibility/private_field.stderr diff --git a/tests/compile-fail/visibility/private_flags.stderr.beta b/tests/compile-fail/visibility/private_flags.stderr similarity index 100% rename from tests/compile-fail/visibility/private_flags.stderr.beta rename to tests/compile-fail/visibility/private_flags.stderr diff --git a/tests/compile-fail/visibility/pub_const.stderr.beta b/tests/compile-fail/visibility/pub_const.stderr similarity index 100% rename from tests/compile-fail/visibility/pub_const.stderr.beta rename to tests/compile-fail/visibility/pub_const.stderr diff --git a/tests/compile.rs b/tests/compile.rs index f3ee9122..7127acee 100644 --- a/tests/compile.rs +++ b/tests/compile.rs @@ -1,26 +1,12 @@ -use std::{ - env, - fs, - ffi::OsStr, - io, - path::Path, -}; - -use walkdir::WalkDir; - -#[test] +// Compiler messages change frequently enough that we can end up with +// an impossible build between error messages emitted on various channels. +// Since https://github.com/dtolnay/trybuild/pull/170 we always need to have a +// `stderr` file for each test so we can't simply ignore the output on different channels. +#[rustversion::attr(beta, test)] +#[allow(dead_code)] fn fail() { - prepare_stderr_files("tests/compile-fail").unwrap(); - let t = trybuild::TestCases::new(); - t.compile_fail("tests/compile-fail/**/*.rs"); - - // `trybuild` will run its tests on `drop` - // We want to get a chance to use its output first - drop(t); - - overwrite_stderr_files("tests/compile-fail").unwrap(); } #[test] @@ -28,81 +14,3 @@ fn pass() { let t = trybuild::TestCases::new(); t.pass("tests/compile-pass/**/*.rs"); } - -// Compiler messages may change between versions -// We don't want to have to track these too closely for `bitflags`, but -// having some message to check makes sure user-facing errors are sensical. -// -// The approach we use is to run the test on all compilers, but only check stderr -// output on beta (which is the next stable release). We do this by default ignoring -// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files -// when we happen to be running on a beta compiler. -fn prepare_stderr_files(path: impl AsRef) -> io::Result<()> { - for entry in WalkDir::new(path) { - let entry = entry?; - - if entry.path().extension().and_then(OsStr::to_str) == Some("beta") { - let renamed = entry.path().with_extension(""); - - // Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta` - // file if it exists. On `beta` compilers, we'll recreate it. On other compilers, - // we don't want to end up checking it anyways. - if renamed.exists() { - fs::remove_file(&renamed)?; - } - - rename_beta_stderr(entry.path(), renamed)?; - } - } - - Ok(()) -} - -// If we want to overwrite the expected compiler output then rename it -// to use our `.stderr.beta` convention. Otherwise the renamed file won't -// actually get picked up on the next run -fn overwrite_stderr_files(path: impl AsRef) -> io::Result<()> { - if env::var("TRYBUILD").ok().filter(|o| o == "overwrite").is_some() { - for entry in WalkDir::new(path) { - let entry = entry?; - - // Look for any `.stderr` files and rename them to `.stderr.beta` - // If there's an existing `.beta` file then we want to remove it - if entry.path().extension().and_then(OsStr::to_str) == Some("stderr") { - let renamed = entry.path().with_extension("stderr.beta"); - - if renamed.exists() { - remove_beta_stderr(&renamed)?; - } - - rename_beta_stderr(entry.path(), renamed)?; - } - } - } - - Ok(()) -} - -#[rustversion::beta] -fn remove_beta_stderr(path: impl AsRef) -> io::Result<()> { - fs::remove_file(path)?; - - Ok(()) -} - -#[rustversion::not(beta)] -fn remove_beta_stderr(_: impl AsRef) -> io::Result<()> { - Ok(()) -} - -#[rustversion::beta] -fn rename_beta_stderr(from: impl AsRef, to: impl AsRef) -> io::Result<()> { - fs::copy(from, to)?; - - Ok(()) -} - -#[rustversion::not(beta)] -fn rename_beta_stderr(_: impl AsRef, _: impl AsRef) -> io::Result<()> { - Ok(()) -}