Skip to content

Commit 0c127e8

Browse files
committed
Life's too short not to use cfg_if
1 parent 3b6b489 commit 0c127e8

File tree

2 files changed

+101
-23
lines changed

2 files changed

+101
-23
lines changed

src/libcore/hint.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -97,36 +97,33 @@ pub fn spin_loop() {
9797
/// elimination.
9898
///
9999
/// This function is a no-op, and does not even read from `dummy`.
100+
#[inline]
100101
#[unstable(feature = "test", issue = "27812")]
101102
pub fn black_box<T>(dummy: T) -> T {
102-
#[cfg(not(
103-
any(
103+
cfg_if! {
104+
if #[cfg(any(
104105
target_arch = "asmjs",
105106
all(
106107
target_arch = "wasm32",
107108
target_os = "emscripten"
108109
)
109-
)
110-
))] {
111-
// we need to "use" the argument in some way LLVM can't
112-
// introspect.
113-
unsafe { asm!("" : : "r"(&dummy)) }
114-
dummy
115-
}
116-
#[cfg(
117-
any(
118-
target_arch = "asmjs",
119-
all(
120-
target_arch = "wasm32",
121-
target_os = "emscripten"
122-
)
123-
)
124-
)] {
125-
// asm.js and emscripten do not support inline assembly
126-
unsafe {
127-
let ret = crate::ptr::read_volatile(&dummy);
128-
crate::mem::forget(dummy);
129-
ret
110+
))] {
111+
#[inline]
112+
unsafe fn black_box_impl<T>(d: T) -> T {
113+
// these targets do not support inline assembly
114+
let ret = crate::ptr::read_volatile(&d);
115+
crate::mem::forget(d);
116+
ret
117+
}
118+
} else {
119+
#[inline]
120+
unsafe fn black_box_impl<T>(d: T) -> T {
121+
// we need to "use" the argument in some way LLVM can't
122+
// introspect.
123+
asm!("" : : "r"(&d));
124+
d
125+
}
130126
}
131127
}
128+
unsafe { black_box_impl(dummy) }
132129
}

src/libcore/internal_macros.rs

+81
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,84 @@ macro_rules! impl_fn_for_zst {
119119
)+
120120
}
121121
}
122+
123+
/// A macro for defining `#[cfg]` if-else statements.
124+
///
125+
/// The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
126+
/// preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
127+
/// emitting the implementation which matches first.
128+
///
129+
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
130+
/// without having to rewrite each clause multiple times.
131+
///
132+
/// # Example
133+
///
134+
/// ```
135+
/// #[macro_use]
136+
/// extern crate cfg_if;
137+
///
138+
/// cfg_if! {
139+
/// if #[cfg(unix)] {
140+
/// fn foo() { /* unix specific functionality */ }
141+
/// } else if #[cfg(target_pointer_width = "32")] {
142+
/// fn foo() { /* non-unix, 32-bit functionality */ }
143+
/// } else {
144+
/// fn foo() { /* fallback implementation */ }
145+
/// }
146+
/// }
147+
///
148+
/// # fn main() {}
149+
/// ```
150+
macro_rules! cfg_if {
151+
// match if/else chains with a final `else`
152+
($(
153+
if #[cfg($($meta:meta),*)] { $($it:item)* }
154+
) else * else {
155+
$($it2:item)*
156+
}) => {
157+
cfg_if! {
158+
@__items
159+
() ;
160+
$( ( ($($meta),*) ($($it)*) ), )*
161+
( () ($($it2)*) ),
162+
}
163+
};
164+
165+
// match if/else chains lacking a final `else`
166+
(
167+
if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
168+
$(
169+
else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
170+
)*
171+
) => {
172+
cfg_if! {
173+
@__items
174+
() ;
175+
( ($($i_met),*) ($($i_it)*) ),
176+
$( ( ($($e_met),*) ($($e_it)*) ), )*
177+
( () () ),
178+
}
179+
};
180+
181+
// Internal and recursive macro to emit all the items
182+
//
183+
// Collects all the negated cfgs in a list at the beginning and after the
184+
// semicolon is all the remaining items
185+
(@__items ($($not:meta,)*) ; ) => {};
186+
(@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
187+
// Emit all items within one block, applying an approprate #[cfg]. The
188+
// #[cfg] will require all `$m` matchers specified and must also negate
189+
// all previous matchers.
190+
cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
191+
192+
// Recurse to emit all other items in `$rest`, and when we do so add all
193+
// our `$m` matchers to the list of `$not` matchers as future emissions
194+
// will have to negate everything we just matched as well.
195+
cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
196+
};
197+
198+
// Internal macro to Apply a cfg attribute to a list of items
199+
(@__apply $m:meta, $($it:item)*) => {
200+
$(#[$m] $it)*
201+
};
202+
}

0 commit comments

Comments
 (0)