From 97f200533058ee40b1b4ba01a6996a994ce8c171 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 17:13:03 +0100 Subject: [PATCH 01/12] Add unstable cfg_if! macro to libcore --- src/libcore/macros.rs | 83 +++++++++++++++++++++++++++++++++++++ src/libcore/tests/cfg_if.rs | 52 +++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 src/libcore/tests/cfg_if.rs diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index ad8ce1af1f6a1..3d45ed8b017e4 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -635,6 +635,89 @@ macro_rules! uninitialized_array { }); } +/// A macro for defining `#[cfg]` if-else statements. +/// +/// The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C +/// preprocessor macro by allowing definition of a cascade of `#[cfg]` cases, +/// emitting the implementation which matches first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code +/// without having to rewrite each clause multiple times. +/// +/// # Example +/// +/// ``` +/// #[macro_use] +/// extern crate cfg_if; +/// +/// cfg_if! { +/// if #[cfg(unix)] { +/// fn foo() { /* unix specific functionality */ } +/// } else if #[cfg(target_pointer_width = "32")] { +/// fn foo() { /* non-unix, 32-bit functionality */ } +/// } else { +/// fn foo() { /* fallback implementation */ } +/// } +/// } +/// +/// # fn main() {} +/// ``` +#[macro_export(local_inner_macros)] +#[unstable(feature = "cfg_if", issue = "59442")] +macro_rules! cfg_if { + // match if/else chains with a final `else` + ($( + if #[cfg($($meta:meta),*)] { $($it:item)* } + ) else * else { + $($it2:item)* + }) => { + cfg_if! { + @__items + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + }; + + // match if/else chains lacking a final `else` + ( + if #[cfg($($i_met:meta),*)] { $($i_it:item)* } + $( + else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } + )* + ) => { + cfg_if! { + @__items + () ; + ( ($($i_met),*) ($($i_it)*) ), + $( ( ($($e_met),*) ($($e_it)*) ), )* + ( () () ), + } + }; + + // Internal and recursive macro to emit all the items + // + // Collects all the negated cfgs in a list at the beginning and after the + // semicolon is all the remaining items + (@__items ($($not:meta,)*) ; ) => {}; + (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + // Emit all items within one block, applying an approprate #[cfg]. The + // #[cfg] will require all `$m` matchers specified and must also negate + // all previous matchers. + cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$m` matchers to the list of `$not` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } + }; + + // Internal macro to Apply a cfg attribute to a list of items + (@__apply $m:meta, $($it:item)*) => { + $(#[$m] $it)* + }; +} + /// Built-in macros to the compiler itself. /// /// These macros do not have any corresponding definition with a `macro_rules!` diff --git a/src/libcore/tests/cfg_if.rs b/src/libcore/tests/cfg_if.rs new file mode 100644 index 0000000000000..2e9784d8543d0 --- /dev/null +++ b/src/libcore/tests/cfg_if.rs @@ -0,0 +1,52 @@ +#![feature(cfg_if)] + +cfg_if! { + if #[cfg(test)] { + use core::option::Option as Option2; + fn works1() -> Option2 { Some(1) } + } else { + fn works1() -> Option { None } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works2() -> bool { false } + } else if #[cfg(test)] { + fn works2() -> bool { true } + } else { + fn works2() -> bool { false } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works3() -> bool { false } + } else { + fn works3() -> bool { true } + } +} + +cfg_if! { + if #[cfg(test)] { + use core::option::Option as Option3; + fn works4() -> Option3 { Some(1) } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works5() -> bool { false } + } else if #[cfg(test)] { + fn works5() -> bool { true } + } +} + +#[test] +fn it_works() { + assert!(works1().is_some()); + assert!(works2()); + assert!(works3()); + assert!(works4().is_some()); + assert!(works5()); +} From c0aabcf038c541660ae2d7e5ada96c2fa240ea4f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:31:37 +0100 Subject: [PATCH 02/12] Remove cfg_if macro from libstd --- src/libstd/macros.rs | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d5dc5f7c4f0df..e00e234997548 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -943,39 +943,3 @@ mod builtin { ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }); } } - -/// A macro for defining `#[cfg]` if-else statements. -/// -/// This is similar to the `if/elif` C preprocessor macro by allowing definition -/// of a cascade of `#[cfg]` cases, emitting the implementation which matches -/// first. -/// -/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code -/// without having to rewrite each clause multiple times. -macro_rules! cfg_if { - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - __cfg_if_items! { - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } - } -} - -macro_rules! __cfg_if_items { - (($($not:meta,)*) ; ) => {}; - (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* } - __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } - } -} - -macro_rules! __cfg_if_apply { - ($m:meta, $($it:item)*) => { - $(#[$m] $it)* - } -} From 3e9d356da57f2bc425c5cd0df93494d9ae302404 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:34:30 +0100 Subject: [PATCH 03/12] Test that cfg_if from prelude can be overriden --- src/libcore/tests/cfg_if_override.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/libcore/tests/cfg_if_override.rs diff --git a/src/libcore/tests/cfg_if_override.rs b/src/libcore/tests/cfg_if_override.rs new file mode 100644 index 0000000000000..b8cd205d3205b --- /dev/null +++ b/src/libcore/tests/cfg_if_override.rs @@ -0,0 +1,16 @@ +#![feature(cfg_if)] + +macro_rules! cfg_if { + (()) => { + mod foo { + fn foo() {} + } + } +} + +cfg_if!{} + +#[test] +fn it_works() { + foo::foo(); +} From 52bd6ad7199272b4eb71ce94f04aac0a114c456c Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:38:52 +0100 Subject: [PATCH 04/12] Add test that overrides cfg_if with the one from crates.io --- src/libcore/Cargo.toml | 1 + src/libcore/tests/cfg_if_override.rs | 2 + src/libcore/tests/cfg_if_stable_override.rs | 55 +++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/libcore/tests/cfg_if_stable_override.rs diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index fa2ab11243b6c..6865525e0c89f 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -21,6 +21,7 @@ path = "../libcore/benches/lib.rs" [dev-dependencies] rand = "0.6" +cfg_if = "1.0" [features] # Make panics and failed asserts immediately abort without formatting any message diff --git a/src/libcore/tests/cfg_if_override.rs b/src/libcore/tests/cfg_if_override.rs index b8cd205d3205b..fc1cc6156a7e9 100644 --- a/src/libcore/tests/cfg_if_override.rs +++ b/src/libcore/tests/cfg_if_override.rs @@ -1,3 +1,5 @@ +//! Test that overriding cfg_if with our own cfg_if macro does not break +//! anything. #![feature(cfg_if)] macro_rules! cfg_if { diff --git a/src/libcore/tests/cfg_if_stable_override.rs b/src/libcore/tests/cfg_if_stable_override.rs new file mode 100644 index 0000000000000..2718b9cab9fa1 --- /dev/null +++ b/src/libcore/tests/cfg_if_stable_override.rs @@ -0,0 +1,55 @@ +//! Test that using cfg_if from the cfg_if crate does not break anything. + +#[macro_use(cfg_if)] +extern crate cfg_if; + +cfg_if! { + if #[cfg(test)] { + use core::option::Option as Option2; + fn works1() -> Option2 { Some(1) } + } else { + fn works1() -> Option { None } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works2() -> bool { false } + } else if #[cfg(test)] { + fn works2() -> bool { true } + } else { + fn works2() -> bool { false } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works3() -> bool { false } + } else { + fn works3() -> bool { true } + } +} + +cfg_if! { + if #[cfg(test)] { + use core::option::Option as Option3; + fn works4() -> Option3 { Some(1) } + } +} + +cfg_if! { + if #[cfg(foo)] { + fn works5() -> bool { false } + } else if #[cfg(test)] { + fn works5() -> bool { true } + } +} + +#[test] +fn it_works() { + assert!(works1().is_some()); + assert!(works2()); + assert!(works3()); + assert!(works4().is_some()); + assert!(works5()); +} From f35f2dfe80ea1350376d2f527fefd1bf538a5b90 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:47:12 +0100 Subject: [PATCH 05/12] Enable cfg_if feature for libstd --- src/libstd/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 296c4c887274e..1710ae09b78d7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -241,6 +241,7 @@ #![feature(bind_by_move_pattern_guards)] #![feature(box_syntax)] #![feature(c_variadic)] +#![feature(cfg_if)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] From 72eed28c8d15e75a6c0dba144c2e486e227d06eb Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:54:45 +0100 Subject: [PATCH 06/12] cfg_if doc-example should use the macro from libcore --- src/libcore/macros.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 3d45ed8b017e4..e45c4afb55fd9 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -647,9 +647,6 @@ macro_rules! uninitialized_array { /// # Example /// /// ``` -/// #[macro_use] -/// extern crate cfg_if; -/// /// cfg_if! { /// if #[cfg(unix)] { /// fn foo() { /* unix specific functionality */ } From f6fbf937f375565df3de7090e352d0beb6d738bc Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:54:58 +0100 Subject: [PATCH 07/12] Remove unnecessary feature(cfg_if) --- src/libcore/tests/cfg_if_override.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/tests/cfg_if_override.rs b/src/libcore/tests/cfg_if_override.rs index fc1cc6156a7e9..16471ec91b1ec 100644 --- a/src/libcore/tests/cfg_if_override.rs +++ b/src/libcore/tests/cfg_if_override.rs @@ -1,6 +1,5 @@ //! Test that overriding cfg_if with our own cfg_if macro does not break //! anything. -#![feature(cfg_if)] macro_rules! cfg_if { (()) => { From 881b5922e10d4edbdfca52ca909fad5e43742cad Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 19:56:11 +0100 Subject: [PATCH 08/12] Fix typo in name of the cfg-if dev-dependency --- src/libcore/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 6865525e0c89f..1790d61558494 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -21,7 +21,7 @@ path = "../libcore/benches/lib.rs" [dev-dependencies] rand = "0.6" -cfg_if = "1.0" +cfg-if = "1.0" [features] # Make panics and failed asserts immediately abort without formatting any message From 168229b1177423610dd69d7d13a10d0ae3eebdd3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 20:09:16 +0100 Subject: [PATCH 09/12] Re-export cfg_if macro from libstd and test --- src/libstd/lib.rs | 4 ++++ src/libstd/tests/cfg_if.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/libstd/tests/cfg_if.rs diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 1710ae09b78d7..dce40160fadac 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -327,6 +327,10 @@ pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert #[stable(feature = "rust1", since = "1.0.0")] pub use core::{unreachable, unimplemented, write, writeln, r#try, todo}; +#[unstable(feature = "cfg_if", issue = "59442")] +pub use core::cfg_if; + + #[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] extern crate alloc as alloc_crate; diff --git a/src/libstd/tests/cfg_if.rs b/src/libstd/tests/cfg_if.rs new file mode 100644 index 0000000000000..cd84202767d9a --- /dev/null +++ b/src/libstd/tests/cfg_if.rs @@ -0,0 +1,14 @@ +pub use std::cfg_if; + +cfg_if! { + if #[cfg(test)] { + fn foo() -> bool { true } + } else { + fn foo() -> bool { false } + } +} + +#[test] +fn cfg_if_test { + assert!(foo()); +} From f915ae4a91ab9e7d44110d7343bf9cf85ffce8ef Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 26 Mar 2019 22:31:06 +0100 Subject: [PATCH 10/12] Choose right cfg-if version number --- src/libcore/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 1790d61558494..8508fa4aa3e57 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -21,7 +21,7 @@ path = "../libcore/benches/lib.rs" [dev-dependencies] rand = "0.6" -cfg-if = "1.0" +cfg-if = "0.1" [features] # Make panics and failed asserts immediately abort without formatting any message From 165882ca0e2a6c60ec11bc2ee7add946c8918b75 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 28 Mar 2019 10:42:38 +0100 Subject: [PATCH 11/12] Update Cargo.lock --- Cargo.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73adb762e485b..279f1f5e31a1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -521,6 +521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "core" version = "0.0.0" dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2074,7 +2075,7 @@ name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2096,7 +2097,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2121,7 +2122,7 @@ name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] From 98e146185d1f12094b42c66d9c5211656b6bb0f8 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 29 Mar 2019 12:21:40 +0100 Subject: [PATCH 12/12] fix build --- src/libcore/macros.rs | 1 + src/libstd/tests/cfg_if.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index e45c4afb55fd9..9cfa70f91954a 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -647,6 +647,7 @@ macro_rules! uninitialized_array { /// # Example /// /// ``` +/// # #![feature(cfg_if)] /// cfg_if! { /// if #[cfg(unix)] { /// fn foo() { /* unix specific functionality */ } diff --git a/src/libstd/tests/cfg_if.rs b/src/libstd/tests/cfg_if.rs index cd84202767d9a..3ecfadba8d3c9 100644 --- a/src/libstd/tests/cfg_if.rs +++ b/src/libstd/tests/cfg_if.rs @@ -1,3 +1,4 @@ +#![feature(cfg_if)] pub use std::cfg_if; cfg_if! { @@ -9,6 +10,6 @@ cfg_if! { } #[test] -fn cfg_if_test { +fn cfg_if_test() { assert!(foo()); }