0

我正在尝试学习 Rust,特别是生命周期和智能指针,并且想知道最生锈的方法。

具体来说,假设我们正在设计一种模拟语言和“分析器”:

a=1 # each line is of form name=number|name
b=2
c=a # a is "copied" to c and should have value 1
a=4 # a and all its references should now have value 4

让我们设计一些虚假的“内存节点”抽象

代码 内存节点
a=1 Node { name: "a", value: 4 }
b=2 Node { name: "b", value: 2 }
c=a Node { name: "c", value: 1 }
a=4 Node { name: "a", value: 4 }

注意:我们只希望存在三个内存节点,而不是像 AST 那样的四个内存节点

为了能够解析变量的值,我必须保持从名称到“内存节点”的上下文

为了保持我的分析器的 API 干净,我不想公开这个上下文。

假设我们的基础结构如下所示:

struct Root {
    pub nodes: Vec<&Node>,
}

struct Node {
    pub name: String,
    pub value: u64,
}

struct Context {
    nodes: HashMap<String, Node>,
}

impl Node {
    fn new(line: &str, context: &mut Context) -> Node {
         // Add self to context
         // If node exists in context, update it and return the same
         // return new node
    }
}

但是,我们不能在 Context 和 Root 中保留 Node 的副本。

一种方法是像Rc<RefCell<Node>>任何地方一样包装节点,这会使客户端 API 不整洁。理想情况下,我希望保持Root包含 Vec&Node作为公共 API。示例实现在这里https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7ec7ecd29eea2626a11b90c829777e30

当我使用生命周期尝试此操作时,我得到一个我无法真正规避的错误 - https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5c5054872806b94a5b3a8ad4a75c1282

它给:

error[E0499]: cannot borrow `context` as mutable more than once at a time
  --> src/main.rs:49:39
   |
43 |     fn new(text: &str) -> Root {
   |                  - let's call the lifetime of this reference `'1`
...
49 |             let node = Node::new(row, &mut context);
   |                                       ^^^^^^^^^^^^ `context` was mutably borrowed here in the previous iteration of the loop
...
52 |         Root { nodes, context }
   |         ----------------------- returning this value requires that `context` is borrowed for `'1`

error[E0505]: cannot move out of `context` because it is borrowed
  --> src/main.rs:52:23
   |
43 |     fn new(text: &str) -> Root {
   |                  - let's call the lifetime of this reference `'1`
...
49 |             let node = Node::new(row, &mut context);
   |                                       ------------ borrow of `context` occurs here
...
52 |         Root { nodes, context }
   |         --------------^^^^^^^--
   |         |             |
   |         |             move out of `context` occurs here
   |         returning this value requires that `context` is borrowed for `'1`

Some errors have detailed explanations: E0499, E0505.
For more information about an error, try `rustc --explain E0499`.

或者,如果可能的话,在不使用智能指针的情况下,还有哪些其他 Rusty 方法可以做到这一点?

4

0 回答 0