【问题标题】:Why is Rust telling "unknown size at compile time" instead of another error in a (invalid) slice to slice assignment?为什么 Rust 告诉“编译时大小未知”而不是(无效)切片到切片分配中的另一个错误?
【发布时间】:2020-07-30 21:47:55
【问题描述】:

我有一段看起来很奇怪的代码,我知道 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
 --> 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}]`

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

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

【问题讨论】:

    标签: rust


    【解决方案1】:

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

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-03
      • 2018-06-06
      • 1970-01-01
      • 2018-05-30
      • 2019-07-22
      • 2021-07-11
      • 2021-09-26
      相关资源
      最近更新 更多