• 1000 Я пытался решить, как определить черту для узлов кода, которые являются операторами или выражениями. Эта черта должна была использоваться для взаимного обхода кода (для целей переписывания). Абстракция, которую я пытался создать, была «узлом кода», который может иметь любое количество дочерних элементов, которые являются операторами или выражениями. Вот как это было:
// Actually these are enums with different payload types for different kinds of exprs/stmts,
// but this is not relevant.
struct Expression;
struct Statement;
trait CodeNode<'a>
where
Self::ExprIter: Iterator<Item = &'a mut Expression>,
Self::StmtIter: Iterator<Item = &'a mut Statement>,
{
type ExprIter;
type StmtIter;
fn child_exprs(&'a mut self) -> Self::ExprIter;
fn child_stmts(&'a mut self) -> Self::StmtIter;
}
Затем эта черта будет реализована для довольно многих типов (у меня есть отдельный тип для разных типов операторов и выражений).
Как я пробовал использовать было:
fn process<'a>(node: &'a mut impl CodeNode<'a>) {
for _stmt in node.child_stmts() {
// ...
}
for _expr in node.child_exprs() {
// ...
}
}
И вот в чем проблема. Компилятор Rust обрабатывает вызов node.child_stmts
как изменяемое заимствование node
для всего времени жизни 'a
, и поэтому он не разрешает вызов node.child_exprs
позже в той же функции. Вот как выглядит ошибка:
error[E0499]: cannot borrow `*node` as mutable more than once at a time
--> src/main.rs:21:18
|
16 | fn process<'a>(node: &'a mut impl CodeNode<'a>) {
| -- lifetime `'a` defined here
17 | for _stmt in node.child_stmts() {
| ------------------
| |
| first mutable borrow occurs here
| argument requires that `*node` is borrowed for `'a`
...
21 | for _expr in node.child_exprs() {
| ^^^^ second mutable borrow occurs here
Я хочу как-то сообщить компилятору о том, что node
реализует CodeNode<'a>
для любого параметра времени жизни, и поэтому он должен использовать два отдельных времени жизни для двух вызовов, но я не могу понять, как это сделать.
Любые предложения приветствуются, у меня нет большого опыта работы с Rust, поэтому, возможно, Мне не хватает более высокоуровневого решения исходной проблемы.