【问题标题】:cannot borrow variable as mutable because it is also borrowed as immutable while building a self-referential HashMap不能将变量借用为可变的,因为在构建自引用 HashMap 时它也被借用为不可变的
【发布时间】:2016-02-20 14:19:03
【问题描述】:

我正在尝试构建一个自我引用的HashMap

use std::collections::HashMap;

struct Node<'a> {
    byte: u8,
    map: HashMap<i32, &'a Node<'a>>,
}

fn main() {
    let mut network = HashMap::<u32, Node>::new();

    network.insert(0, Node { byte: 0, map: HashMap::<i32, &Node>::new() });
    network.insert(1, Node { byte: 1, map: HashMap::<i32, &Node>::new() });

    let zeroeth_node = network.get(&0).unwrap();
    let mut first_node = network.get_mut(&1).unwrap();

    first_node.map.insert(-1, zeroeth_node);
}

我遇到了借用检查器错误,但我不明白它的来源 - 是我更新错误的 HashMap 的方法,还是我对它的自我引用使用?

错误:

<anon>:15:26: 15:33 error: cannot borrow `network` as mutable because it is also borrowed as immutable [E0502]
<anon>:15     let mut first_node = network.get_mut(&1).unwrap();
                                   ^~~~~~~
<anon>:14:24: 14:31 note: previous borrow of `network` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `network` until the borrow ends
<anon>:14     let zeroeth_node = network.get(&0).unwrap();
                                 ^~~~~~~
<anon>:18:2: 18:2 note: previous borrow ends here
<anon>:8 fn main() {
...
<anon>:18 }
          ^

【问题讨论】:

标签: hashmap rust borrow-checker


【解决方案1】:

回答

这些类型的结构在 Rust 中很难构建。您的示例中缺少的主要内容是使用RefCell,它允许共享引用。 RefCells 将 Rust 的借用检查从编译时转移到运行时,从而允许您传递内存位置。但是,不要在任何地方开始使用RefCell,因为它只适用于这样的情况,如果您尝试在已经可变借用的东西时可变地借用,RefCells 将导致您的程序使用panic!。这仅适用于在network 中创建的Nodes;您将无法创建纯粹存在于单个 Node 内部的 Nodes。

Solution

use std::collections::HashMap;
use std::cell::RefCell;
#[derive(Debug)]
struct Node<'a> {
    byte: u8,
    map: HashMap<i32, &'a RefCell<Node<'a>>>,
}

fn main() {
    let mut network = HashMap::new();

    network.insert(0, RefCell::new(Node { byte: 0, map: HashMap::new() }));
    network.insert(1, RefCell::new(Node { byte: 1, map: HashMap::new() }));

    let zero_node = network.get(&0).unwrap();
    zero_node.borrow_mut().byte = 2;

    let first_node = network.get(&1).unwrap();
    first_node.borrow_mut().map.insert(-1, zero_node);

    println!("{:#?}", network);
}

【讨论】:

    猜你喜欢
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多