为什么 Rust 告诉“编译时大小未知”而不是(无效)切片到切片分配中的另一个错误?

phi*_*611 4 rust

我有一段看起来很奇怪的代码,我知道 Rust 编译器拒绝它,但我不明白具体的错误消息。

TL; 博士; 为什么 Rust 以“在编译时没有已知的大小”而不是“非法语法”或“不能将切片分配给切片”之类的东西拒绝这一点?

fn main() {
    let mut data1 = vec![0, 1, 2, 3].as_slice();
    let mut data2 = vec![8, 9].as_slice();
    data1[1..3] = *data2; // of course this is illegal; but I don't understand the error message
}
Run Code Online (Sandbox Code Playgroud)

这是代码。理论上它应该用 slice 中data1的数据替换子切片data2。(例如,正确的方法是 for 循环,我知道!)。但是让我们来看看这个。Rust 编译器说:

error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
 --> src\main.rs:4:5
  |
4 |     data1[1..3] = *data2;
  |     ^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
Run Code Online (Sandbox Code Playgroud)

为什么 , 处的错误data1[1..3]仅出现在作业的左侧?我希望 Rust 编译器告诉错误是在赋值的右侧,甚至是整个赋值。类似的东西"can't assign a slice to a slice"。

但是为什么 Rust 会准确地传达这个信息呢?为什么data1[1..3]在这种情况下大小未知?当然[{integer}]不是Sized。但是此时应该不需要堆栈分配了吧?我希望有任何其他错误消息。

Pet*_*aro 5

我看不到您作业左侧的切片,编译器也看不到!

总是尽量减少你的例子,大多数时候这样做你会发现编译器实际上在抱怨什么。所以,如果你想写这个:

let data1 = [0u8, 1, 2, 3];
let x = data1[1..3];
Run Code Online (Sandbox Code Playgroud)

您会看到,编译器在您的示例中实际抱怨的是什么:

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> src/main.rs:4:9
  |
4 |     let x = data1[1..3];
  |         ^   ----------- help: consider borrowing here: `&data1[1..3]`
  |         |
  |         doesn't have a size known at compile-time
Run Code Online (Sandbox Code Playgroud)

您看,[T]和之间存在巨大差异&[T]! [T]是Ts的连续序列,而&[T]是该连续序列的动态大小视图。前者没有静态已知的大小,而后者有。

而在你说你使用了这个Vec::as_slice方法之前,之后你尝试了一个切片,那就是:

// Type of `data1` is `&[u8]`
let data1 = vec![0u8, 1, 2, 3].as_slice();

// Type of `x` is `[u8]`
// (which doesn't have a size known at compile-time
let x = data1[1..3];  
Run Code Online (Sandbox Code Playgroud)

所以我相信你的问题的答案是编译器没有达到它实际上可以查看作业另一侧的地步,因为当它试图找出左侧时它已经发现了一个问题:在编译时没有已知大小的表达式。

现在,如果您真的要在左侧写一个切片:

let mut data1 = [0u8, 1, 2, 3];
let data2 = [8u8, 9];

&mut data1[1..3] = &data2[..];
Run Code Online (Sandbox Code Playgroud)

然后编译器会抱怨左侧的无效性质(除其他外):

error[E0070]: invalid left-hand side of assignment
 --> src/main.rs:6:22
  |
6 |     &mut data1[1..3] = &data2[..];
  |     ---------------- ^
  |     |
  |     cannot assign to this expression
Run Code Online (Sandbox Code Playgroud)