rust - 为什么我不能在将 &mut 引用传递给接受泛型类型的函数后重用它?

标签 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();
}

这种情况下的错误是:

error[E0382]: use of moved value: `*data`
  --> src/main.rs:14:5
   |
9  |         let mut buf = io::Cursor::new(data);
   |                                       ---- value moved here
...
14 |     data.len();
   |     ^^^^ value used here after move
   |
   = note: move occurs because `data` has type `&mut std::vec::Vec<u8>`, which does not implement the `Copy` trait

io::Cursor::new 的签名使得它拥有其参数的所有权。在这种情况下,参数是对 Vec 的可变引用。

pub fn new(inner: T) -> Cursor<T>

这对我来说有点道理;因为 Cursor::new 拥有它的参数(而不是引用)的所有权,所以我们以后不能使用该值。同时它没有意义:我们基本上只传递了一个可变引用,而游标无论如何都会超出范围。 在 produce_data 函数中,我们还向 take_reference 传递了一个可变引用,当再次尝试使用 data 时,它不会产生错误,这与在 take_reference 中。

我发现可以使用 Cursor.into_inner() 来“回收”引用,但是手动操作感觉有点奇怪,因为在正常用例中,借用检查器是完全有能力自己完成。

这个问题有没有比使用 .into_inner() 更好的解决方案?也许关于借用检查器还有其他我不明白的地方?

最佳答案

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

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

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

        use_cursor(&mut buf);
    }

    data.len();
}

1 — 这是因为当前的编译器架构只允许在强制站点上已知源类型和目标类型的情况下进行强制转换。

关于rust - 为什么我不能在将 &mut 引用传递给接受泛型类型的函数后重用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48143889/

相关文章:

while循环中借用的rustc_serialize::Json值不够活

windows - 为什么 Windows 上 time::Duration 的纳秒值降至最接近的 100 倍数?

rust - 如何从函数返回 &Path?

iterator - 提取对辅助函数的迭代器调用链

reference - 为什么我可以返回对本地文字的引用,而不是对变量的引用?

rust - 如果我想将单个可变对象传递给函数的多个参数,我该怎么办?

rust - 如何确保将正确的 HTML 元素从 JavaScript 传递到我的 Rust 函数?

json - 如何解析 JSON 文件?

rust - 请求消息值必须在静态生命周期内有效

rust - 为什么不能在同一结构中存储值和对该值的引用?