rust - 为什么借用检查器不明白借用切片的不同部分从根本上是可以的?

标签 rust borrow-checker

split_at_mut函数(用于在索引处拆分可变切片)需要实现不安全代码( according to the Rust book )。但书中也说:“借用切片的不同部分从根本上是可以的,因为两个切片不重叠”。
我的问题:为什么借用检查器不明白借用切片的不同部分从根本上是可以的? (是否有原因阻止借用检查器理解此规则,或者只是由于某种原因尚未实现?)
使用 Rust 1.48 尝试建议的代码仍然会导致书中显示的错误:

fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = slice.len();

    assert!(mid <= len);

    (&mut slice[..mid], &mut slice[mid..])
}

fn main() {
    let mut vector = vec![1, 2, 3, 4, 5, 6];
    let (left, right) = split_at_mut(&mut vector, 3);
    println!("{:?}, {:?}", left, right);
}
给出错误信息:
error[E0499]: cannot borrow `*slice` as mutable more than once at a time
 --> src/main.rs:6:30
  |
1 | fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
  |                        - let's call the lifetime of this reference `'1`
...
6 |     (&mut slice[..mid], &mut slice[mid..])
  |     -------------------------^^^^^--------
  |     |     |                  |
  |     |     |                  second mutable borrow occurs here
  |     |     first mutable borrow occurs here
  |     returning this value requires that `*slice` is borrowed for `'1`

最佳答案

Why does the borrow checker not understand that borrowing different parts of a slice is fundamentally okay?


因为一般情况下是做不到的。当然,在这种情况下很明显 &slice[..mid]&slice[mid..]是不相交的,但是一旦你摆脱了琐碎的案件,复杂性就会飙升,很快就变得不可能了。
这些特殊的琐碎情况没有特别实现,因为:
  • 具有允许明显不相交的切片借用但不允许任何更复杂的东西的语言功能是不直观的,并且可以使初学者认为他们可以做的事情比他们实际做的要多
  • 这些特殊情况实际上只能归结为几种模式,其中大部分可以通过 split_at 完成。及其可变对应物
  • 无法使用 Index 可靠地将其扩展到任何内容trait,这意味着 (&slice[..mid], &slice[mid..])将有效,但 (&vec[..mid], &vec[mid..])不会,这更不一致。当然,这可以通过制作 Vec 来解决。一种内在的语言,那么 VecDeque 呢?或用户定义的数据结构?它只会导致太多的不一致,进而导致更多的不一致,这是 Rust 想要避免的。
  • 关于rust - 为什么借用检查器不明白借用切片的不同部分从根本上是可以的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66313625/

    相关文章:

    rust - 我应该在哪里放置一个静态库,以便我可以将它与 Rust 程序链接起来?

    lambda - 为什么这个闭包需要内联或 `dyn` ? `dyn` 在这里做什么?

    rust - 匹配后如何修改值?

    rust - "Does not live long enough"`Weak<RefCell<_>>` 错误

    rust - 在 &mut self 方法中展开成员变量时无法移出借用的内容

    data-structures - 用Rust进行交接锁定

    video - GStreamer 的最低开销源格式?

    rust - 将盒装特征转换为 Rust 中的可变特征引用

    rust - 避免在结果链中多次调用 `map_err`

    rust - 进行多次可变和不可变借贷的最佳实践是什么? [复制]