gpt4 book ai didi

rust - 为什么我不能在 &mut T 工作时使用 &mut Box 一次多次借用可变变量?

转载 作者:行者123 更新时间:2023-11-29 08:06:02 25 4
gpt4 key购买 nike

我试图在 Rust 中实现一个链表,但我在理解这两个函数之间的区别时遇到了一些困难:

enum List<T> {
Nil,
Cons(T, Box<List<T>>)
}

fn foo<T>(list: &mut Box<List<T>>) {
match **list {
List::Nil => return,
List::Cons(ref mut head, ref mut tail) => {
// ...
}
}
}

fn bar<T>(list: &mut List<T>) {
match *list {
List::Nil => return,
List::Cons(ref mut head, ref mut tail) => {
// ...
}
}
}

foo 编译失败,错误如下:

error[E0499]: cannot borrow `list` (via `list.1`) as mutable more than once at a time
--> src/main.rs:66:34
|
66 | List::Cons(ref mut head, ref mut rest) => {
| ------------ ^^^^^^^^^^^^ second mutable borrow occurs here (via `list.1`)
| |
| first mutable borrow occurs here (via `list.0`)
...
69 | }
| - first borrow ends here

但是,bar 可以完美地编译和运行。为什么 bar 有效,但 foo 无效?我使用的是 Rust 版本 1.25。

最佳答案

这可以简化为

fn foo(v: &mut Box<(i32, i32)>) {
match **v {
(ref mut head, ref mut tail) => {}
}
}

fn foo(v: &mut Box<(i32, i32)>) {
let (ref mut head, ref mut tail) = **v;
}

问题是 Box是一种奇怪的中间类型。

回顾 Rust 的历史,Box由编译器特殊处理;它知道 Box 的很多细节,但这意味着它是“神奇的”,没有其他人可以实现像 Box 这样的东西.

RFC 130提议改变那个;制作 Box “只是另一种类型”。不幸的是,这还没有完全过渡。

细节有细微差别,但目前的借用检查器基本上句法处理模式匹配,而不是语义。它需要这样做以防止一些不健全的问题。

在未来,非词法生命周期(NLL)会神奇地解决这个问题;你不需要做任何事情(万岁!)。

在那之前,您可以显式返回到 &mut T有了这个丑陋的 Blob :

match *&mut **list {

或调用DerefMut明确地:

match *std::ops::DerefMut::deref_mut(list) {

但是,有 very little reason to accept a &mut Box<T> .

另见:

关于rust - 为什么我不能在 &mut T 工作时使用 &mut Box<T> 一次多次借用可变变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50237774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com