Rust切片所有权超出其范围

时间:2016-04-06 09:00:55

标签: rust

我疯狂地试图围绕Rust生命周期问题。运行以下代码时:

use std::fs::File;
use std::io::Read;
use std::clone::Clone;

const BUFSIZE : usize = 4096;

struct LexBuf<T: Read> {
    f: T,
    buf: [u8; BUFSIZE],
    tail: usize,
    head: usize
}

impl <T : Read> LexBuf<T> {
    fn fetch(&mut self) {
        let keepSize = self.head - self.tail + 1;
        let mut tmpBuf;
        {
            let tmpSlice = &self.buf[self.tail..self.head+1];
            tmpBuf = tmpSlice.clone();
        }
        &mut self.buf[0..keepSize]
            .clone_from_slice(tmpBuf);
        let mut n = self.f
            .read(&mut self.buf[keepSize..]).unwrap();
        if n < BUFSIZE - keepSize {
            self.buf[keepSize+n] = 0;
        }
    }
}

我希望事实tmpSlice在其自己的范围内允许我之后借用self.buf但似乎借用检查员并不同意,因为它说{{1}借用在tmpSlice范围结束。

1 个答案:

答案 0 :(得分:6)

当然它不同意,因为tmpBuf的生命周期不会在内部块中结束。调用切片的clone()返回该切片的副本,即指针和长度的副本。出于所有意图和目的,tmpSlice.clone()返回的切片相当于tmpSlice,包括其生命周期。因为您将它分配给外部作用域中的tmpBuf,所以它自然会超出内部块的范围。

实际上,如果Rust允许,您的代码将会中断 - clone_from_slice()源和目标可能会重叠。例如,如果self.tail0self.head10,则源和目标完全重叠。

不幸的是,没有办法创建一个在运行时确定大小的固定大小的堆栈数组,所以解决这个问题的唯一方法是通过调用to_owned()to_vec()来分配堆上的数据。在切片上获取Vec<u8>

或者,您可以分配第二个固定大小的数组,该数组保证不小于结构中的数组,并将其用作临时空间。您需要使用clone_from_slice()两次。