将&mut引用传递给接受通用类型的函数后,为什么不能重用它?

Sam*_*rty 7 rust borrow-checker

该代码为什么不编译:

fn use_cursor(cursor: &mut io::Cursor<&mut Vec<u8>>) {
    // do some work
}

fn take_reference(data: &mut Vec<u8>) {
    {
        let mut buf = io::Cursor::new(data);

        use_cursor(&mut buf);
    }

    data.len();
}

fn produce_data() {
    let mut data = Vec::new();
    take_reference(&mut data);
    data.len();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下的错误是:

fn use_cursor(cursor: &mut io::Cursor<&mut Vec<u8>>) {
    // do some work
}

fn take_reference(data: &mut Vec<u8>) {
    {
        let mut buf = io::Cursor::new(data);

        use_cursor(&mut buf);
    }

    data.len();
}

fn produce_data() {
    let mut data = Vec::new();
    take_reference(&mut data);
    data.len();
}
Run Code Online (Sandbox Code Playgroud)

的签名io::Cursor::new必须具有其论点的所有权。在这种情况下,该参数是对的可变引用Vec

pub fn new(inner: T) -> Cursor<T>
Run Code Online (Sandbox Code Playgroud)

这对我来说很有意义;因为Cursor::new拥有其参数(而不是引用)的所有权,我们以后不能再使用该值。同时,这没有任何意义:本质上,我们只传递可变的引用,然后游标将超出范围。在produce_data函数中,我们还向传递了一个可变引用take_reference,并且尝试data再次使用时不会产生错误,这与inside不同take_reference

我发现可以通过使用来“回收”引用Cursor.into_inner(),但是手动进行引用有点奇怪,因为在正常的用例中,借位检查器完全可以自己进行引用。

有没有比使用更好的解决方案.into_inner()?也许还有其他我不了解的借位检查器?

Fra*_*gné 9

通常,当您将可变引用传递给函数时,编译器会隐式执行reborrow。这会产生寿命较短的新借用。

当参数为通用参数(且不是形式&mut T)时,编译器不会自动进行此重新借用。但是,您可以通过取消引用现有的可变引用然后再次引用来手动完成此操作:

fn take_reference(data: &mut Vec<u8>) {
    {
        let mut buf = io::Cursor::new(&mut *data);

        use_cursor(&mut buf);
    }

    data.len();
}
Run Code Online (Sandbox Code Playgroud)