summaryrefslogtreecommitdiff
path: root/src/macros.rs
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2019-09-30 16:02:01 -0400
committerAaron Hill <aa1ronham@gmail.com>2019-10-27 20:59:38 -0400
commit5dfc2c82854eede618f35c4511e941506f0e76d0 (patch)
treecfce2e74639a01d259e450108a32f4849b28762f /src/macros.rs
parent53bdffc028632907958bbd03ff88182b2b20a6cc (diff)
downloadrust-libc-5dfc2c82854eede618f35c4511e941506f0e76d0.tar.gz
Add support for declaring 'const fn'
Add a new feature to enable this, since `const extern fn` support is unstable
Diffstat (limited to 'src/macros.rs')
-rw-r--r--src/macros.rs98
1 files changed, 89 insertions, 9 deletions
diff --git a/src/macros.rs b/src/macros.rs
index 14a2804664..da39270633 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -121,16 +121,96 @@ macro_rules! s_no_extra_traits {
);
}
-#[allow(unused_macros)]
-macro_rules! f {
- ($(pub fn $i:ident($($arg:ident: $argty:ty),*) -> $ret:ty {
- $($body:stmt);*
- })*) => ($(
- #[inline]
- pub unsafe extern fn $i($($arg: $argty),*) -> $ret {
- $($body);*
+// This is a pretty horrible hack to allow us to conditionally mark
+// some functions as 'const', without requiring users of this macro
+// to care about the "const-extern-fn" feature.
+//
+// When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
+// in the expanded function.
+//
+// When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'.
+// Note that the expression matched by the macro is exactly the same - this allows
+// users of this macro to work whether or not 'const-extern-fn' is enabled
+//
+// Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks.
+// This is because 'const unsafe extern fn' won't even parse on older compilers,
+// so we need to avoid emitting it at all of 'const-extern-fn'.
+//
+// Specifically, moving the 'cfg_if' into the macro body will *not* work.
+// Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emiited
+// into user code. The 'cfg' gate will not stop Rust from trying to parse the
+// 'pub const unsafe extern fn', so users would get a compiler error even when
+// the 'const-extern-fn' feature is disabled
+//
+// Note that users of this macro need to place 'const' in a weird position
+// (after the closing ')' for the arguments, but before the return type).
+// This was the only way I could satisfy the following two requirements:
+// 1. Avoid ambuguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn'
+// 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same
+// 'f!' block
+cfg_if! {
+ if #[cfg(feature = "const-extern-fn")] {
+ #[allow(unused_macros)]
+ macro_rules! f {
+ ($(pub $({$constness:ident})* fn $i:ident(
+ $($arg:ident: $argty:ty),*
+ ) -> $ret:ty {
+ $($body:stmt);*
+ })*) => ($(
+ #[inline]
+ pub $($constness)* unsafe extern fn $i($($arg: $argty),*
+ ) -> $ret {
+ $($body);*
+ }
+ )*)
}
- )*)
+
+ #[allow(unused_macros)]
+ macro_rules! const_fn {
+ ($($({$constness:ident})* fn $i:ident(
+ $($arg:ident: $argty:ty),*
+ ) -> $ret:ty {
+ $($body:stmt);*
+ })*) => ($(
+ #[inline]
+ $($constness)* fn $i($($arg: $argty),*
+ ) -> $ret {
+ $($body);*
+ }
+ )*)
+ }
+
+ } else {
+ #[allow(unused_macros)]
+ macro_rules! f {
+ ($(pub $({$constness:ident})* fn $i:ident(
+ $($arg:ident: $argty:ty),*
+ ) -> $ret:ty {
+ $($body:stmt);*
+ })*) => ($(
+ #[inline]
+ pub unsafe extern fn $i($($arg: $argty),*
+ ) -> $ret {
+ $($body);*
+ }
+ )*)
+ }
+
+ #[allow(unused_macros)]
+ macro_rules! const_fn {
+ ($($({$constness:ident})* fn $i:ident(
+ $($arg:ident: $argty:ty),*
+ ) -> $ret:ty {
+ $($body:stmt);*
+ })*) => ($(
+ #[inline]
+ fn $i($($arg: $argty),*
+ ) -> $ret {
+ $($body);*
+ }
+ )*)
+ }
+ }
}
#[allow(unused_macros)]