【发布时间】:2020-03-14 18:53:40
【问题描述】:
为什么下面的代码不能编译(playground):
use std::collections::HashMap;
fn main() {
let mut h: HashMap<u32, u32> = HashMap::new();
h.insert(0, 0);
h.insert(1, h.remove(&0).unwrap());
}
借用检查器抱怨:
error[E0499]: cannot borrow `h` as mutable more than once at a time
--> src/main.rs:6:17
|
6 | h.insert(1, h.remove(&0).unwrap());
| - ------ ^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
然而,代码是安全的,最后一行的几乎机械转换使其可以编译 (playground):
//h.insert(1, h.remove(&0).unwrap());
let x = h.remove(&0).unwrap();
h.insert(1, x);
据我了解,此类问题已通过非词汇生命周期得到解决。 This question 就是一个例子,还有很多其他的。
到底有没有一些微妙之处使得第一个变体不正确,所以 Rust 拒绝它是正确的?还是所有情况下 NLL 功能仍未完成?
【问题讨论】:
-
我不同意 (a) 包含完整的错误消息,以便搜索引擎更容易找到帖子,或 (b) 在标题中包含完整的句子,以便人们可以轻松识别是否该帖子与他们的问题相关的是“琐碎的”或“风格的”,但无论您的船是什么。
-
Shepmaster/Stargateur 我认为如果您将自己限制在有用的编辑(即错误消息)中,您的编辑会下降很多,而不是仅仅以您认为更好的方式重新措辞(例如删除“但是”),因为问题作者可能不同意。
-
@Shepmaster 我已将完整的错误消息添加到问题中,再次查看,省略的部分似乎有助于理解问题。
-
天啊。我们不是在谈论在这里获得导弹发射代码,是吗?如果有人需要,我有一些备用的感冒药。当我的编辑被拒绝时,我会在我的日历(实际上只是 URL)中添加一个带有提醒集的注释。我稍后会回来,在那里我可以从新的视角和“战斗期间”所做的所有编辑的总和中受益。在问题被拒绝一周后,我认为我从未进行过编辑。
-
@Stargateur 好的,现在我开始明白你为什么冒犯了,我欠你一个道歉。我没有仔细检查您的编辑,这在我看来就像是对 Shepmaster 编辑的又一次回滚,我已经在某种编辑战争中拒绝了。如果我注意到你小心地删除了标题编辑,我自己会采取不同的行动。对此感到抱歉。
标签: rust borrow-checker