rust 给出cfg时禁用不必要的不安全警告

wfveoks0  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(193)

我有一个结构的两个版本,一个在特性启用时启用,另一个在特性未启用时启用,如下所示。问题是一个包含 unsafe 方法,另一个没有。所以当这些函数在库的其他部分被调用时,我用unsafe { }块将它们包围起来。当我的库在未启用特性的情况下编译时,我得到以下警告:
不必要的unsafe
当此警告不适用时,即当功能未启用时,如何绕过/禁用此警告。

#[cfg(feature = "my-feature")]
pub struct MyStruct {
    // some fields
}

#[cfg(not(feature = "my-feature"))]
pub struct MyStruct {
    // some different fields
}

#[cfg(feature = "my-feature")]
impl MyStruct {
    pub unsafe fn my_func() {}
}

#[cfg(not(feature = "my-feature"))]
impl MyStruct {
    pub fn my_func() {}
}

fn main() {
    // I want to get rid of this unsafe when its not needed.
    unsafe { MyStruct::my_func() };
}
cx6n0qe3

cx6n0qe31#

如果这些情况仅在库中,那么您可以不太麻烦地使用宏:

macro_rules! call {
    // For static methods.
    {
        unsafe {
            $($method:ident)::+ ( $($arg:expr),* $(,)? )
        }
    } => {{
        #[cfg(feature = "my-feature")]
        let v = unsafe { $($method)::+ ( $($arg),* ) };
        #[cfg(not(feature = "my-feature"))]
        let v = $($method)::+ ( $($arg),* );
        v
    }};
    // For instance methods.
    {
        unsafe {
            $object:ident . $method:ident ( $($arg:expr),* $(,)? )
        }
    } => {{
        #[cfg(feature = "my-feature")]
        let v = unsafe { $object . $method ( $($arg),* ) };
        #[cfg(not(feature = "my-feature"))]
        let v = $object . $method ( $($arg),* );
        v
    }};
}

call!(unsafe { MyStruct::my_func() });
call!(unsafe { v.my_method() });

这个宏不允许泛型或复杂表达式作为接收器。扩展它以支持泛型应该相当容易;支持复杂表达式可能需要proc宏。
有一种更好的编写宏的方法:与其在内部要求unsafe,并将调用 Package 在cfg中,不如在内部做一些不安全的事情,这样就总是在外部要求unsafe。这也解决了泛型和复杂接收器的问题:

pub(crate) unsafe fn always_unsafe() {}

macro_rules! call {
    ($($call:tt)+) => {{
        $crate::always_unsafe();
        $($call)*
    }};
}

unsafe {
    call!(MyStruct::my_func());
}
unsafe {
    call!(v.my_method());
}

相关问题