How do I change a function's qualifiers via conditional compilation?

后端 未结 1 1751
死守一世寂寞
死守一世寂寞 2020-12-02 01:45

I have a function that is capable of being implemented as a const:

#![feature(const_fn)]

// My crate would have:

const fn very_complicated_log         


        
相关标签:
1条回答
  • 2020-12-02 02:20

    Macros to the rescue!

    #![cfg_attr(feature = "const-fn", feature(const_fn))]
    
    #[cfg(not(feature = "const-fn"))]
    macro_rules! maybe_const_fn {
        ($($tokens:tt)*) => {
            $($tokens)*
        };
    }
    
    #[cfg(feature = "const-fn")]
    macro_rules! maybe_const_fn {
        ($(#[$($meta:meta)*])* $vis:vis $ident:ident $($tokens:tt)*) => {
            $(#[$($meta)*])* $vis const $ident $($tokens)*
        };
    }
    
    maybe_const_fn! {
        #[allow(unused)] // for demonstration purposes
        pub fn very_complicated_logic(a: u8, b: u8) -> u8 {
            internally_complicated_logic(a, b)
        }
    }
    
    maybe_const_fn! {
        fn internally_complicated_logic(a: u8, b: u8) -> u8 {
            a * b
        }
    }
    
    #[cfg(test)]
    mod tests {
        use super::*;
    
        #[cfg(feature = "const-fn")]
        #[test]
        fn use_in_const() {
            const ANSWER: u8 = very_complicated_logic(1, 2);
            drop(ANSWER);
        }
    
        #[test]
        fn use_in_variable() {
            let answer: u8 = very_complicated_logic(1, 2);
            drop(answer);
        }
    }
    

    Along with this in Cargo.toml:

    [features]
    const-fn = []
    

    Since macros can only expand to complete pieces of syntax (i.e. a macro cannot simply expand to const), we have to wrap the whole function in the macro and leave some parts of it unparsed so that we can inject const in the appropriate place. Then, the parser can parse the whole thing as a function definition.

    Attributes and visibility qualifiers need special treatment, because they must appear before const. I am using the vis matcher (available since Rust 1.30.0) to simplify the macro's implementation.

    0 讨论(0)
提交回复
热议问题