rust 在文件链实现中绕过借用检查器

bhmjp9jg  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(119)

我试图实现一个简单的文件链。不幸的是,我的BufRead::fill_buf实现产生了一个借用检查错误。

impl BufRead for FileChain {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        loop {
            let buf = self.stream.fill_buf()?;
            if !buf.is_empty() {
                return Ok(buf);
            } if let Some(filename) = self.future_files.pop() {
                self.stream = BufReader::new(File::open(&filename)?);
            } else {
                return Ok(&[])
            }
        }
    }
}

个字符
您可以找到完整的类定义here(56行)。
我认为这类似于已知的借用检查器问题,描述了here,这里和here。基本上,检查器认为buf引用块stream改变。然而,return bufstream更新不能同时发生。
现有的解决方案(例如来自here)不能在这里应用,因为我没有HashMap/Vector,并且我受到BufRead API的限制。我也不能使用Polonius,因为我只能使用稳定的功能。
我的问题是:有没有可能使用安全的代码来修改这些代码而不牺牲速度?2如果不可能,有没有一种方法可以使用不安全的代码来覆盖借用检查器?

kx5bkwkv

kx5bkwkv1#

有没有一种方法可以使用不安全代码覆盖借用检查器?
虽然使用unsafe并不能关闭借用检查器,但它确实允许你绕过它的一些保护措施。例如,我相信,这是合理的:

fn fill_buf(&mut self) -> io::Result<&[u8]> {
    loop {
        // unsafe: we either return a reference into self (which prevents
        // the caller from mutating self until dropping that reference),
        // or we proceed to mutate self. This is safe under borrowing
        // rules, but fails to compile due to limitations of the current
        // borrow checker. Here we use `transmute()` to temporarily
        // decouple the reference from self (it is reassigned the lifetime
        // of self on returning). Note that the safe code without
        // `transmute()` compiles under Polonius.
        unsafe {
            let buf = std::mem::transmute::<_, &'static [u8]>(self.stream.fill_buf()?);
            if !buf.is_empty() {
                return Ok(buf);
            }
        }
        if let Some(filename) = self.future_files.pop() {
            self.stream = BufReader::new(File::open(&filename)?);
        } else {
            return Ok(&[]);
        }
    }
}

字符串
当使用unsafe时,你需要自己证明代码是正确的--上面的代码在unsafe旁边的注解中记录了原因,这被认为是最佳实践。请记住,unsafe使你能够比安全的方式更进一步地欺骗。例如,修改签名以返回错误的Result<&'static [u8]>仍然可以编译,虽然它使功能明显不健全。这就是为什么在性能不是最重要的情况下最好避免使用unsafe

相关问题