From 56058b588c0a85bf2dca54f8a744b6d507a12e46 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 12:29:33 -0700 Subject: [PATCH 01/12] Add an "impl_arbitrary" feature to enable implementing `Arbitrary`. Fixes #248. --- Cargo.toml | 2 ++ src/lib.rs | 24 ++++++++++++++++++++++++ tests/arbitrary.rs | 17 +++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/arbitrary.rs diff --git a/Cargo.toml b/Cargo.toml index be9e05ad..2e2d86e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,11 +29,13 @@ walkdir = "2.3" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" +arbitrary = "1" [features] default = [] example_generated = [] rustc-dep-of-std = ["core", "compiler_builtins"] +impl_arbitrary = [] [package.metadata.docs.rs] features = ["example_generated"] diff --git a/src/lib.rs b/src/lib.rs index 935e432f..6cbc2a1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -820,6 +820,8 @@ macro_rules! __impl_bitflags { result } } + + __impl_arbitrary_for_bitflags!($BitFlags); }; // Every attribute that the user writes on a const is applied to the @@ -931,6 +933,28 @@ macro_rules! __impl_bitflags { }; } +// When "arbitrary" is not enabled, emit code to implement the `Arbitrary` trait. +#[cfg(feature = "impl_arbitrary")] +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __impl_arbitrary_for_bitflags { + ($BitFlags:ident) => { + impl<'a> arbitrary::Arbitrary<'a> for $BitFlags { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + Self::from_bits(u.arbitrary()?).ok_or_else(|| arbitrary::Error::IncorrectFormat) + } + } + }; +} + +// When "arbitrary" is not enabled, don't emit any code for it. +#[cfg(not(feature = "impl_arbitrary"))] +#[macro_export(local_inner_macros)] +#[doc(hidden)] +macro_rules! __impl_arbitrary_for_bitflags { + ($BitFlags:ident) => {}; +} + #[cfg(feature = "example_generated")] pub mod example_generated; diff --git a/tests/arbitrary.rs b/tests/arbitrary.rs new file mode 100644 index 00000000..8544c316 --- /dev/null +++ b/tests/arbitrary.rs @@ -0,0 +1,17 @@ +#![cfg(feature = "impl_arbitrary")] + +use arbitrary::Arbitrary; + +bitflags::bitflags! { + struct Color: u32 { + const RED = 0x1; + const GREEN = 0x2; + const BLUE = 0x4; + } +} + +#[test] +fn test_arbitary() { + let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]); + let _color = Color::arbitrary(&mut unstructured); +} From 66be4264436da3de5fdd9f22f2dfa356335b5275 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 13:27:04 -0700 Subject: [PATCH 02/12] Update src/lib.rs Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com> --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6cbc2a1a..b28ff1b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -933,9 +933,9 @@ macro_rules! __impl_bitflags { }; } -// When "arbitrary" is not enabled, emit code to implement the `Arbitrary` trait. +// When "impl_arbitrary" is enabled, emit code to implement the `Arbitrary` trait. #[cfg(feature = "impl_arbitrary")] -#[macro_export(local_inner_macros)] +#[macro_export] #[doc(hidden)] macro_rules! __impl_arbitrary_for_bitflags { ($BitFlags:ident) => { @@ -947,9 +947,9 @@ macro_rules! __impl_arbitrary_for_bitflags { }; } -// When "arbitrary" is not enabled, don't emit any code for it. +// When "impl_arbitrary" is not enabled, don't emit any code for it. #[cfg(not(feature = "impl_arbitrary"))] -#[macro_export(local_inner_macros)] +#[macro_export] #[doc(hidden)] macro_rules! __impl_arbitrary_for_bitflags { ($BitFlags:ident) => {}; From ad754db3d26e3453c10837aca21fb31847014eac Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 13:26:41 -0700 Subject: [PATCH 03/12] Test impl_arbitrary in CI. This enables impl_arbitrary when example_generated is enabled. --- .github/workflows/rust.yml | 2 +- Cargo.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ffe0edad..7de62f2d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -32,7 +32,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --features example_generated + args: --features example_generated,impl_arbitrary embedded: name: Build (embedded) diff --git a/Cargo.toml b/Cargo.toml index 2e2d86e2..6e0cdc83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ exclude = ["bors.toml"] [dependencies] core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } compiler_builtins = { version = '0.1.2', optional = true } +arbitrary = { version = "1", optional = true } [dev-dependencies] trybuild = "1.0" @@ -33,7 +34,7 @@ arbitrary = "1" [features] default = [] -example_generated = [] +example_generated = ["impl_arbitrary", "arbitrary"] rustc-dep-of-std = ["core", "compiler_builtins"] impl_arbitrary = [] From dec18af1507dfa79d8e08c4827994bd377cbfbd2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 13:32:15 -0700 Subject: [PATCH 04/12] Document the "impl_arbitrary" feature in the README.md. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 0da0f853..a2841c5f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ and this to your source code: use bitflags::bitflags; ``` +Enable the `impl_arbitrary` feature to enable implementations of the +[`Arbitrary`] trait for the generated structures. + +[`Arbitrary`]: https://docs.rs/arbitrary/1.0.1/arbitrary/trait.Arbitrary.html + ## Rust Version Support The minimum supported Rust version is 1.46 due to use of associated constants and const functions. From d970ee0fc4e17436c5b2acd10f377ae7e6a00316 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 13:46:07 -0700 Subject: [PATCH 05/12] Use absolute paths to `arbirary` symbols. --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b28ff1b1..18e33848 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -939,9 +939,9 @@ macro_rules! __impl_bitflags { #[doc(hidden)] macro_rules! __impl_arbitrary_for_bitflags { ($BitFlags:ident) => { - impl<'a> arbitrary::Arbitrary<'a> for $BitFlags { - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - Self::from_bits(u.arbitrary()?).ok_or_else(|| arbitrary::Error::IncorrectFormat) + impl<'a> ::arbitrary::Arbitrary<'a> for $BitFlags { + fn arbitrary(u: &mut ::arbitrary::Unstructured<'a>) -> ::arbitrary::Result { + Self::from_bits(u.arbitrary()?).ok_or_else(|| ::arbitrary::Error::IncorrectFormat) } } }; From fee72add6657b58001a1e97d81e92b32e4d63d52 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 18 Aug 2021 14:05:25 -0700 Subject: [PATCH 06/12] Depend on and re-export "arbitrary". Drop the "impl_arbitrary" feature, now that we can just use "arbitrary". --- Cargo.toml | 3 +-- README.md | 4 ++-- src/lib.rs | 22 +++++++++++++------- tests/arbitrary.rs | 2 +- tests/compile-pass/redefinition/arbitrary.rs | 20 ++++++++++++++++++ 5 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 tests/compile-pass/redefinition/arbitrary.rs diff --git a/Cargo.toml b/Cargo.toml index 6e0cdc83..159b4c27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,8 @@ arbitrary = "1" [features] default = [] -example_generated = ["impl_arbitrary", "arbitrary"] +example_generated = ["arbitrary"] rustc-dep-of-std = ["core", "compiler_builtins"] -impl_arbitrary = [] [package.metadata.docs.rs] features = ["example_generated"] diff --git a/README.md b/README.md index a2841c5f..e7f780c0 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ and this to your source code: use bitflags::bitflags; ``` -Enable the `impl_arbitrary` feature to enable implementations of the -[`Arbitrary`] trait for the generated structures. +Enable the `arbitrary` feature to enable implementations of the [`Arbitrary`] +trait for the generated structures. [`Arbitrary`]: https://docs.rs/arbitrary/1.0.1/arbitrary/trait.Arbitrary.html diff --git a/src/lib.rs b/src/lib.rs index 18e33848..eb33bb5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -933,28 +933,36 @@ macro_rules! __impl_bitflags { }; } -// When "impl_arbitrary" is enabled, emit code to implement the `Arbitrary` trait. -#[cfg(feature = "impl_arbitrary")] +// When "arbitrary" is enabled, emit code to implement the `Arbitrary` trait. +#[cfg(feature = "arbitrary")] #[macro_export] #[doc(hidden)] macro_rules! __impl_arbitrary_for_bitflags { ($BitFlags:ident) => { - impl<'a> ::arbitrary::Arbitrary<'a> for $BitFlags { - fn arbitrary(u: &mut ::arbitrary::Unstructured<'a>) -> ::arbitrary::Result { - Self::from_bits(u.arbitrary()?).ok_or_else(|| ::arbitrary::Error::IncorrectFormat) + impl<'a> $crate::_arbitrary::Arbitrary<'a> for $BitFlags { + fn arbitrary( + u: &mut $crate::_arbitrary::Unstructured<'a> + ) -> $crate::_arbitrary::Result { + Self::from_bits(u.arbitrary()?).ok_or_else(|| $crate::_arbitrary::Error::IncorrectFormat) } } }; } -// When "impl_arbitrary" is not enabled, don't emit any code for it. -#[cfg(not(feature = "impl_arbitrary"))] +// When "arbitrary" is not enabled, don't emit any code for it. +#[cfg(not(feature = "arbitrary"))] #[macro_export] #[doc(hidden)] macro_rules! __impl_arbitrary_for_bitflags { ($BitFlags:ident) => {}; } +// Re-export `arbitrary` so that our macro expansions can refer to it by a +// known name. +#[cfg(feature = "arbitrary")] +#[doc(hidden)] +pub extern crate arbitrary as _arbitrary; + #[cfg(feature = "example_generated")] pub mod example_generated; diff --git a/tests/arbitrary.rs b/tests/arbitrary.rs index 8544c316..a3b2f694 100644 --- a/tests/arbitrary.rs +++ b/tests/arbitrary.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "impl_arbitrary")] +#![cfg(feature = "arbitrary")] use arbitrary::Arbitrary; diff --git a/tests/compile-pass/redefinition/arbitrary.rs b/tests/compile-pass/redefinition/arbitrary.rs new file mode 100644 index 00000000..a9ef6791 --- /dev/null +++ b/tests/compile-pass/redefinition/arbitrary.rs @@ -0,0 +1,20 @@ +use bitflags::bitflags; + +// Checks for possible errors caused by overriding names used by `bitflags!` internally. + +mod arbitrary {} +mod _arbitrary {} + +bitflags! { + struct Test: u8 { + const A = 1; + } +} + +fn main() { + #[cfg(feature = "arbitrary")] + { + let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]); + let _test = Test::arbitrary(&mut unstructured); + } +} From 8efeb65118153decee03bf2caaceff2101418ee7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 19 Aug 2021 13:09:13 -0700 Subject: [PATCH 07/12] Update Cargo.toml Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com> --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 159b4c27..9762cd20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ walkdir = "2.3" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -arbitrary = "1" [features] default = [] From fc99c5e3066b5eaf4bfbf45e67bf190c5fe763d1 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 19 Aug 2021 13:09:34 -0700 Subject: [PATCH 08/12] Update .github/workflows/rust.yml Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com> --- .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 7de62f2d..ffe0edad 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -32,7 +32,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --features example_generated,impl_arbitrary + args: --features example_generated embedded: name: Build (embedded) From 230933b1e86149a001f26062abb70a78f878cc42 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 19 Aug 2021 13:40:15 -0700 Subject: [PATCH 09/12] Fix a typo. --- tests/arbitrary.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/arbitrary.rs b/tests/arbitrary.rs index a3b2f694..a6b25e97 100644 --- a/tests/arbitrary.rs +++ b/tests/arbitrary.rs @@ -11,7 +11,7 @@ bitflags::bitflags! { } #[test] -fn test_arbitary() { +fn test_arbitrary() { let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]); let _color = Color::arbitrary(&mut unstructured); } From 411d15264efc3ba67ac778cb65660386eea2a2e0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 19 Aug 2021 13:40:26 -0700 Subject: [PATCH 10/12] Move the compile-pass test into a toplevel test. And make the other changes suggested by @konsumlamm. --- tests/arbitrary-redefinition.rs | 23 ++++++++++++++++++++ tests/compile-pass/redefinition/arbitrary.rs | 20 ----------------- 2 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 tests/arbitrary-redefinition.rs delete mode 100644 tests/compile-pass/redefinition/arbitrary.rs diff --git a/tests/arbitrary-redefinition.rs b/tests/arbitrary-redefinition.rs new file mode 100644 index 00000000..0e961eeb --- /dev/null +++ b/tests/arbitrary-redefinition.rs @@ -0,0 +1,23 @@ +#![cfg(feature = "arbitrary")] + +extern crate arbitrary as a; + +use a::Arbitrary; +use bitflags::bitflags; + +// Checks for possible errors caused by overriding names used by `bitflags!` internally. + +mod arbitrary {} +mod _arbitrary {} + +bitflags! { + struct Test: u8 { + const A = 1; + } +} + +#[test] +fn test_arbitrary_redefinition() { + let mut unstructured = a::Unstructured::new(&[0_u8; 256]); + let _test = Test::arbitrary(&mut unstructured); +} diff --git a/tests/compile-pass/redefinition/arbitrary.rs b/tests/compile-pass/redefinition/arbitrary.rs deleted file mode 100644 index a9ef6791..00000000 --- a/tests/compile-pass/redefinition/arbitrary.rs +++ /dev/null @@ -1,20 +0,0 @@ -use bitflags::bitflags; - -// Checks for possible errors caused by overriding names used by `bitflags!` internally. - -mod arbitrary {} -mod _arbitrary {} - -bitflags! { - struct Test: u8 { - const A = 1; - } -} - -fn main() { - #[cfg(feature = "arbitrary")] - { - let mut unstructured = arbitrary::Unstructured::new(&[0_u8; 256]); - let _test = Test::arbitrary(&mut unstructured); - } -} From 1a1e3753af5f78912629159cf70f18caa487b5ee Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 24 Aug 2021 22:28:40 -0700 Subject: [PATCH 11/12] Avoid adding `arbitrary` to the `example_generated` feature. Add it to the docs.rs enabled features instead, as suggested in the PR comments. --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9762cd20..fed83f2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,8 +33,8 @@ serde_json = "1.0" [features] default = [] -example_generated = ["arbitrary"] +example_generated = [] rustc-dep-of-std = ["core", "compiler_builtins"] [package.metadata.docs.rs] -features = ["example_generated"] +features = ["example_generated", "arbitrary"] From fab01fa629fdb63fa3f37dff905bf34705e34068 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 25 Aug 2021 09:29:55 -0700 Subject: [PATCH 12/12] Re-enable the arbitrary feature in CI. --- .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 ffe0edad..3242d3ed 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -32,7 +32,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --features example_generated + args: --features example_generated,arbitrary embedded: name: Build (embedded)