gpt4 book ai didi

rust - 无法可变地借用 RefCell 内的内容,即使在前一个可变借用的范围已经结束之后

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

考虑下面的代码

use std::{cell::RefCell, rc::Rc};

type NodeRef = Rc<RefCell<_Node>>;

#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}

impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);

self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};

for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}

println!("done {}", self.id);
}
}

#[derive(Debug)]
struct Node(NodeRef);

impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec![],
})))
}

fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}

fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}

fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);

d.add_edge(&a);
d.add_edge(&b);

e.add_edge(&b);
e.add_edge(&c);

f.add_edge(&d);
f.add_edge(&e);

f.add(Node::new(6));
}

运行时生成的输出是

at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5

这将创建一个图形

F--E--A 
\ \
\ B
\ /
D
\
C

我试图在整个图中传播一个值,所以它从 F 开始,然后到达 E 和 D。从 E 到 A 和 B,没有任何错误。然后从 D 开始,运行时 panic 说可变借用的 RefCell 约束已被打破。

它似乎正在考虑从先前使用 B 调用回调的可变借用,然而,_Node::add 中的可变借用 (current_data_raw) 有一个有限的范围,在范围结束后,我应该被允许再次可变地借用该值。从输出来看,当第二次为节点 B 调用该函数时,该函数的整个第一次调用已经退出,而不仅仅是可变借用范围。

我在这里错过了什么?

最佳答案

What am I missing here?

你的算法坏了。您可以通过将此调试代码添加到匹配的 Some 臂中来看到这一点:

{
let a = current_data.borrow();
let b = other.borrow();

assert_ne!(a.id, b.id);
}

这失败了:

thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25

您正在尝试同时两次借用完全相同的节点

关于rust - 无法可变地借用 RefCell 内的内容,即使在前一个可变借用的范围已经结束之后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54277188/

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