Skip to content
  • bors's avatar
    Auto merge of #1536 - Aaron1011:feature/const-fn, r=gnzlbg · d742eedf
    bors authored
    Add support for making functions `const`
    
    PR https://github.com/rust-lang/rust/pull/64906 adds the ability to write `const extern fn` and `const unsafe extern fn`, which will allow manys functions in `libc` to become `const`.
    
    This is particuarly useful for functions which correspond to C macros (e.g. `CMSG_SPACE`). In C, these macros are constant expressions, allowing them to be used when declaring arrays. However, since the corresponding `libc` functions are not `const`, writing equivalent Rust code is impossible. Users must either perform an unecessary heap allocation, or pull in `bindgen` to evaluate the macro for specific values (e.g. `CMSG_SPACE(1)`).
    
    However, the syntax `const extern fn` is not currently parsed by rust. To allow libc to use this without breaking backwards compatibility (i.e. bumping the minimum Rust version), I've taken the following approach:
    
    1. A new off-by-default feature `extern-const-fn` is added to `libc`.
    2. The internal `f!` macro has two versions, selected at compile-time by a `cfg_if`. When `extern-const-fn` is enabled, the declared `f!` macro passes through the `const` keyword from the macro user to the final definition (`pub const unsafe extern fn foo`. When  `extern-const-fn` is disabled, the `const` keyword passed by the macro user is discarded, resulting in a plain `pub extern const fn` being declared.
    
    Unfortunately, I couldn't manage to get `macro_rules` to accept a normal `const` token in the proper place (after `pub`). I had to resort to placing it in curly brackets:
    
    ```rust
    pub {const} fn foo(val: u8) -> i8 {
    }
    ```
    
    The `f!` macro then translates this to a function definition with `const` in the proper position.
    
    I'd appreciate it if someone who's more familiar with `macro_rules!` could see if I missed a way to get the desired syntax.
    d742eedf