我目前正在编写一些不安全的代码,需要在一定程度上手动管理生存期,并将这些生存期expose 给外部用户.我一直在编写测试,虽然编写测试来验证编译代码的正确性非常容易(至少在可能出现未定义行为的情况下是这样),但我一直希望确保某些类型的不健全代码不能编译.

假设我有下面这个假想的例子:

pub struct MyBox<T> {
    ptr: *mut T,
}

impl<T> MyBox<T> {
    fn new(t: T) -> Self {
        MyBox {
            ptr: Box::into_raw(Box::new(t)),
        }
    }
    fn get(&self) -> &T {
        unsafe { &*self.ptr }
    }
}
impl<T> Drop for MyBox<T> {
    fn drop(&mut self) {
        unsafe { Box::from_raw(self.ptr) }
    }
}

fn test<'a>() -> &'a i32 {
    MyBox::new(7).get()
}

我如何才能确保test函数继续无法从Rust的测试框架编译?

显然,只是将错误的代码放到一个单独的文件中,并使用实际的测试函数作为美化的构建脚本,这是可行的,但这会变得非常繁琐和尴尬,特别是当我想测试的不只是一两个糟糕的示例时.如果有帮助,我不关心错误的细节,只关心错误是否存在.

推荐答案

您可以将其编写为compile_fail attr的doctest,这样您就可以在一个注释中编写多个预期同时失败的测试.

/// ```compile_fail,E0515
/// use path_to::MyBox;
///
/// fn test<'a>() -> &'a i32 {
///     MyBox::new(7).get()
/// }
/// ```
fn _doc_test() {}

,E0515表示您预期的错误号,这样可以避免任何其他可能导致测试出现假阴性的错误.(如果Cargo 不是每晚运行,则忽略此错误号判断)

请注意,这要求您的机箱为lib而不是bin,因为目前doctest不支持bin.(第#50784期)

Rust相关问答推荐

何时可以在Rust中退出异步操作?

两个相关特征的冲突实现错误

返回的future 不是`发送`

在Rust中有没有办法在没有UB的情况下在指针和U64之间进行转换?

Pin<;&;mut可能将Uninit<;T>;>;合并为Pin<;&;mut T>;

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

如果包名称与bin名称相同,并且main.ars位于工作区的同一 crate 中,则无法添加对lib.ars的依赖

Rust将String上的迭代器转换为&;[&;str]

找不到 .has_func 或 .get_func 的 def

如何将 struct 数组放置在另一个 struct 的末尾而不进行内存分段

使用启用优化的 alloc 会导致非法指令崩溃

如何基于常量在Rust中跳过一个测试

Sized问题的动态调度迭代器Rust

仅当函数写为闭包时才会出现生命周期错误

Rust Serde 为 Option:: 创建反序列化器

在每个循环迭代中删除borrow

在异步 Rust 中,Future 如何确保它只调用最近的 Waker?

如何在 nom 中构建负前瞻解析器?

tokio async rust 的 yield 是什么意思?

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?