如何将不可变切片传递给需要 &mut impl Read 的 fn?

How to pass immutable slice to fn that takes an &mut impl Read?

我有一个 fn 看起来像这样:

use std::io::Read;

fn read_something(file: &mut impl Read) {
    let _ = file.read(&mut [0; 8]);
}

当我像这样将 Vec 的一片传递给它时:

fn main() {
    let vector = vec![1, 2, 3, 4];
    read_something(&mut &vector[..]);
}

它工作正常。但是,当我先将切片保存到变量中时,它不会编译:

fn main() {
    let vector = vec![1, 2, 3, 4];
    let slice = &vector[..];
    read_something(&mut slice);
}

编译器告诉我,我

cannot borrow as mutable

Playground

这两种情况有何不同? 为什么即使 vector 也未声明为可变的,第一个示例仍然有效? 我怎样才能将 &[u8] 切片传递到 fn 中,它会吃掉 &mut impl Read

How can I pass a &[u8] slice into that fn, that eats a &mut impl Read?

mut添加到保存切片的变量中:

let vector = vec![1, 2, 3, 4];
let mut slice = &vector[..];
read_something(&mut slice);

请注意,这会使切片可变,这意味着它可以被修改以引用不同的数据(read_something() 使用)。它不授予 slice 改变不可变向量的能力。

How do these two cases differ? Why does the first example work even though the vector is not declared as mutable either?

在第一种情况下,向量是不可变的,但是保存切片 的未命名临时变量是 。您的第一个案例脱糖为:

let vector = vec![1, 2, 3, 4]; // immutable Vec
let mut tmp = &vector[..]; // mutable slice referring to immutable Vec
read_something(&mut tmp);
// here `tmp` may be pointing to different content
// (e.g. a subset of the vector, or something static)

向量不需要是可变的,因为 Read::read() impl for &[u8] 不会尝试修改切片的内容,它只会修改切片(概念上是 元组) 本身。它可以做到这一点,因为 Read 是为 &[u8] 实现的,所以当 <&[u8] as Read>::read() 接收到 &mut self 时,它的完整类型是 &mut &[u8] - 对一片的可变引用不可变数据。

Read::read() for &[u8] 所做的是将接收到的切片替换为包含该切片尚未读取部分的较小切片。 (这允许将“相同”切片传递给 read() 以最终耗尽所有数据。)由于您读入的 8 字节缓冲区大于用作读取源的 4 字节切片,因此修改后的 tmp 切片在 read_something() returns (playground).

之后将为空