为什么 Rust 告诉"unknown size at compile time"而不是(无效)切片中的另一个错误来切片分配?



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

TL;DR为什么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
}

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

error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
--> srcmain.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}]`

为什么data1[1..3]的错误只在分配的左侧?我期望Rust编译器告诉错误在赋值的右边,甚至在整个赋值的右边。类似"can't assign a slice to a slice"

但为什么Rust会说出这样的信息呢?为什么在这种情况下data1[1..3]的大小未知?当然,[{integer}]不是Sized。但是在这一点上不应该有必要的堆栈分配吗?我期待任何其他错误消息。

我看不到赋值左侧的切片,编译器也看不到!

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

let data1 = [0u8, 1, 2, 3];
let x = data1[1..3];

你会看到,在你的例子中,编译器实际上在抱怨什么:

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

你看,[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];  

因此,我相信你的问题的答案是,编译器没有达到可以真正查看赋值的另一边的地步,因为当它试图找出左边时,它已经发现了一个问题:一个在编译时没有已知大小的表达式。

现在,如果你真的在左手边写一个切片:

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

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

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

最新更新