Rust:绕过文件链实现中的借用检查器

问题描述 投票:0回答:1

我正在尝试实现一个简单的文件链。不幸的是,我的

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(&[])
            }
        }
    }
}
error[E0506]: cannot assign to `self.stream` because it is borrowed
40 |     fn fill_buf(&mut self) -> io::Result<&[u8]> {
   |                 - let's call the lifetime of this reference `'1`
41 |         loop {
42 |             let buf = self.stream.fill_buf()?;
   |                       ---------------------- `self.stream` is borrowed here
43 |             if !buf.is_empty() {
44 |                 return Ok(buf);
   |                        ------- returning this value requires that `self.stream` is borrowed for `'1`
45 |             } if let Some(filename) = self.future_files.pop() {
46 |                 self.stream = BufReader::new(File::open(&filename)?);
   |                 ^^^^^^^^^^^ `self.stream` is assigned to here but it was already borrowed

您可以在此处找到完整的类定义(56 行)。

我认为这与已知的借用检查器问题类似,如hereherehere所述。 基本上,检查者认为

buf
参考阻止
stream
发生变化。但是,
return buf
stream
更新不能同时发生。

现有的解决方案(例如来自这里)不能在这里应用,因为我没有HashMap/Vector,并且我受到

BufRead
API的限制。我也无法使用
polonius
,因为我只能使用稳定的功能。

我的问题是:是否可以使用安全代码修改此代码而不牺牲速度?如果这是不可能的,有没有办法使用不安全的代码覆盖借用检查器?

rust io borrow-checker
1个回答
0
投票

有没有办法使用不安全的代码覆盖借用检查器?

虽然使用 unsafe 不会关闭借用检查器,但它确实允许您绕过它的一些安全措施。例如,这样编译:

fn fill_buf(&mut self) -> io::Result<&[u8]> {
    loop {
        {
            let buf =
                unsafe { 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(&[]);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.