Skip to content

Commit

Permalink
fix: Ensure that const extern fn is always enabled
Browse files Browse the repository at this point in the history
In [1] this conditional was dropped in favor of a Cargo feature, which
was turned on by default in [2]. However, this did not help the case
where `--no-default-features` is passed.

Unfortunately we still can't drop this config entirely since `ctest`
cannot parse the syntax, so change back to useing a `cfg` to control
constness rather than a Cargo feature.

Additionally, remove a portion of the macro's comment that is no longer
relevant.

Fixes: rust-lang#4149

[1]: rust-lang#4105
[2]: rust-lang#4134

(backport <rust-lang#4151>)
(cherry picked from commit e18ee8c)
  • Loading branch information
tgross35 committed Nov 26, 2024
1 parent 83490a7 commit 5d2b17f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ cargo-args = ["-Zbuild-std=core"]
rustc-std-workspace-core = { version = "1.0.0", optional = true }

[features]
default = ["const-extern-fn", "std"]
default = ["std"]
std = []
rustc-dep-of-std = ['align', 'rustc-std-workspace-core']
extra_traits = []
Expand Down
5 changes: 5 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const ALLOWED_CFGS: &'static [&'static str] = &[
"freebsd13",
"freebsd14",
"freebsd15",
// FIXME(ctest): this config shouldn't be needed but ctest can't parse `const extern fn`
"libc_const_extern_fn",
"libc_deny_warnings",
"libc_thread_local",
"libc_ctest",
Expand Down Expand Up @@ -80,6 +82,9 @@ fn main() {
set_cfg("libc_thread_local");
}

// Set unconditionally when ctest is not being invoked.
set_cfg("libc_const_extern_fn");

// check-cfg is a nightly cargo/rustc feature to warn when unknown cfgs are used across the
// codebase. libc can configure it if the appropriate environment variable is passed. Since
// rust-lang/rust enforces it, this is useful when using a custom libc fork there.
Expand Down
45 changes: 18 additions & 27 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,40 +167,31 @@ macro_rules! e {
)*);
}

// 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.
// This is a pretty horrible hack to allow us to conditionally mark some functions as 'const',
// without requiring users of this macro to care "libc_const_extern_fn".
//
// When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
// in the expanded function.
// When 'libc_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'.
// When 'libc_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
// users of this macro to work whether or not 'libc_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'.
// so we need to avoid emitting it at all of 'libc_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 emitted
// 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 ambiguity 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
// Specifically, moving the 'cfg_if' into the macro body will *not* work. Doing so would cause the
// '#[cfg(libc_const_extern_fn)]' to be emitted 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 'libc_const_extern_fn' feature is disabled.

// FIXME(ctest): ctest can't handle `const extern` functions, we should be able to remove this
// cfg completely.
// FIXME(ctest): ctest can't handle `$(,)?` so we use `$(,)*` which isn't quite correct.
cfg_if! {
if #[cfg(feature = "const-extern-fn")] {
/// Define an `unsafe` function that is const as long as `const-extern-fn` is enabled.
if #[cfg(libc_const_extern_fn)] {
/// Define an `unsafe` function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! f {
($(
$(#[$attr:meta])*
Expand All @@ -214,7 +205,7 @@ cfg_if! {
)*)
}

/// Define a safe function that is const as long as `const-extern-fn` is enabled.
/// Define a safe function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! safe_f {
($(
$(#[$attr:meta])*
Expand All @@ -228,7 +219,7 @@ cfg_if! {
)*)
}

/// A nonpublic function that is const as long as `const-extern-fn` is enabled.
/// A nonpublic function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! const_fn {
($(
$(#[$attr:meta])*
Expand All @@ -242,7 +233,7 @@ cfg_if! {
)*)
}
} else {
/// Define an `unsafe` function that is const as long as `const-extern-fn` is enabled.
/// Define an `unsafe` function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! f {
($(
$(#[$attr:meta])*
Expand All @@ -256,7 +247,7 @@ cfg_if! {
)*)
}

/// Define a safe function that is const as long as `const-extern-fn` is enabled.
/// Define a safe function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! safe_f {
($(
$(#[$attr:meta])*
Expand All @@ -270,7 +261,7 @@ cfg_if! {
)*)
}

/// A nonpublic function that is const as long as `const-extern-fn` is enabled.
/// A nonpublic function that is const as long as `libc_const_extern_fn` is enabled.
macro_rules! const_fn {
($(
$(#[$attr:meta])*
Expand Down

0 comments on commit 5d2b17f

Please sign in to comment.