diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ffe0edad..b7b2486e 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 --features example_generated embedded: name: Build (embedded) diff --git a/Cargo.toml b/Cargo.toml index 4476122a..9c7c7aa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,13 +25,11 @@ 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" [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..a2d3193b 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; } @@ -407,6 +405,7 @@ macro_rules! __impl_all_bitflags { #[allow(non_snake_case)] trait __BitFlags { $( + #[allow(deprecated)] const $Flag: $T = 0; )+ } @@ -440,86 +439,59 @@ macro_rules! __impl_bitflags { )* } ) => { - impl $crate::_core::fmt::Debug for $BitFlags { - fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_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 } - )* - } + impl $crate::__private::core::fmt::Debug for $BitFlags { + fn fmt(&self, f: &mut $crate::__private::core::fmt::Formatter) -> $crate::__private::core::fmt::Result { + // 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::_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(" | ")?; } 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,12 +530,12 @@ 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 }) + $crate::__private::core::option::Option::Some(Self{ bits }) } else { - None + $crate::__private::core::option::Option::None } } @@ -572,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)] @@ -746,50 +718,10 @@ 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 { - const NUM_FLAGS: usize = { - #[allow(unused_mut)] - let mut num_flags = 0; - - $( - #[allow(unused_doc_comments, unused_attributes)] - $(#[$attr $($args)*])* - { - num_flags += 1; - } - )* + /// 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 _; - num_flags - }; - const OPTIONS: [$BitFlags; NUM_FLAGS] = [ - $( - #[allow(unused_doc_comments, unused_attributes)] - $(#[$attr $($args)*])* - $BitFlags::$Flag, - )* - ]; - let mut start = 0; - - $crate::_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; @@ -804,6 +736,7 @@ macro_rules! __impl_bitflags { num_flags }; + const OPTIONS: [$BitFlags; NUM_FLAGS] = [ $( #[allow(unused_doc_comments, unused_attributes)] @@ -811,37 +744,40 @@ macro_rules! __impl_bitflags { $BitFlags::$Flag, )* ]; + #[allow(unused_doc_comments, unused_attributes)] 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{ + $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 } }) } } - 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 +787,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 +795,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 +805,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 +813,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 +823,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 +831,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 +841,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 +849,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 +859,18 @@ 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 { + use $crate::__private::core::iter::Extend; + let mut result = Self::empty(); result.extend(iterator); result @@ -954,7 +892,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) } @@ -1670,14 +1608,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)"); @@ -1836,8 +1774,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] @@ -1867,7 +1805,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] @@ -1952,13 +1890,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); + 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(), None); let flags = Flags::empty(); @@ -1967,8 +1926,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); } } 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 b/tests/compile-fail/cfg/multi.stderr new file mode 100644 index 00000000..be9ba21c --- /dev/null +++ b/tests/compile-fail/cfg/multi.stderr @@ -0,0 +1,17 @@ +error[E0428]: the name `FOO` is defined multiple times + --> tests/compile-fail/cfg/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_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compile-fail/cfg/multi.stderr.beta b/tests/compile-fail/cfg/multi.stderr.beta deleted file mode 100644 index 75960547..00000000 --- a/tests/compile-fail/cfg/multi.stderr.beta +++ /dev/null @@ -1,35 +0,0 @@ -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 - | -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_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info) 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 64% rename from tests/compile-fail/non_integer_base/all_defined.stderr.beta rename to tests/compile-fail/non_integer_base/all_defined.stderr 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 @@ -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); | ++++++ + 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-pass/no_prelude.rs b/tests/compile-pass/no_prelude.rs new file mode 100644 index 00000000..c54b7a31 --- /dev/null +++ b/tests/compile-pass/no_prelude.rs @@ -0,0 +1,14 @@ +#![no_implicit_prelude] + +extern crate bitflags; + +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() {} 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(()) -}