错误 [E0502]: 不能借用 `cloned_game` 作为不可变的,因为它也被借用为可变的

时间:2021-04-11 09:18:15

标签: rust borrow-checker

我是 Rust 的新手。我正在尝试使用递归解决问题。在递归函数中,我克隆了游戏的状态,然后从向量中取出每对元素并使用 try_add_to() 对它们进行变异,然后检查游戏是否已解决。

fn try_find_solution(game: &GameState) -> Option<GameState> {
    let mut cloned_game = game.clone();

    for split_index in 1..cloned_game.cups.len() - 1 {
        // Need two mutable references from the vector. Use split_at_mut() to allow this.
        let (a, b) = cloned_game.cups.split_at_mut(split_index);
        let first_cup = a.last_mut().unwrap();

        for second_cup in b.iter_mut() {
            if first_cup.try_add_to(second_cup) || second_cup.try_add_to(first_cup) {
                if cloned_game.is_solved() {
                    return Some(cloned_game);
                }
                else {
                    // let solution = try_find_solution(&cloned_game);
                    // @TODO.
                }
            }
        }
    }

    None
}

我遇到了以下错误。

error[E0502]: cannot borrow `cloned_game` as immutable because it is also borrowed as mutable
  --> src/main.rs:31:20
   |
26 |         let (a, b) = cloned_game.cups.split_at_mut(split_index);
   |                      ---------------- mutable borrow occurs here
...
30 |             if first_cup.try_add_to(second_cup) || second_cup.try_add_to(first_cup) {
   |                --------- mutable borrow later used here
31 |                 if cloned_game.is_solved() {
   |                    ^^^^^^^^^^^ immutable borrow occurs here

我想我明白为什么会出现这个错误,但不知道如何在没有完全重新设计解决方案的情况下修复它。有什么我可以做的吗?

1 个答案:

答案 0 :(得分:0)

如果这是您尝试强制执行某些操作的尝试,我可能不会使用递归。除了最简单的解决方案,您可能会达到递归限制。此外,您将不得不进行大量的克隆,因为每个堆栈都会创建自己的游戏状态克隆。

至于你原来的问题,最好的办法是避免同时持有这些引用。

例如,这不会编译:

fn hello_world(s: &mut [u8]){
    let (a,b) = s.split_at_mut(1);
    let c = s.len();
    drop((a,b,c));
}

...但这确实:

fn hello_world(s: &mut [u8]){
    let (a,b) = s.split_at_mut(1);
    drop((a,b));
    
    let c = s.len();
    drop(c);
}

...因为我们不会强行将 ab 保持到最后。如果您可以将 .is_solved() 调用提取到循环外,那应该可以。