【问题标题】:"BorrowMutError" using the Interior Mutability Pattern使用内部可变性模式的“BorrowMutError”
【发布时间】:2020-12-30 23:44:29
【问题描述】:

我正在尝试使用内部可变性模式来共享可变引用。

但是,当我尝试使用与它共享的结构中的引用时,程序会出现以下错误:

thread 'main' panicked at 'already borrowed: BorrowMutError'

代码如下:

use std::rc::Rc;
use std::cell::RefCell;

fn main() {
    let game = Game::init();
    game.start();
}

struct Game {
    ecs: Rc<RefCell<Ecs>>,
}

impl Game {
    pub fn init() -> Game {
        let ecs = Rc::new(RefCell::new(Ecs::new()));
        ecs.borrow_mut().register_systems(vec![
            Box::new(Renderer {
                ecs: Rc::clone(&ecs),
            }),
        ]);
        Game {
            ecs: Rc::clone(&ecs),
        }
    }

    pub fn start(&self) {
        self.ecs.borrow_mut().update();
    }
}

struct Ecs {
    systems: Vec<Box<dyn System>>,
}

impl Ecs {
    fn new() -> Ecs {
        Ecs {
            systems: vec![],
        }
    }

    fn register_systems(&mut self, systems: Vec<Box<dyn System>>) {
        self.systems = systems;
    }

    fn update(&self) {
        for system in self.systems.iter() {
            system.update();
        }
    }

    fn test(&self) {
        println!("done!");
    }
}

trait System {
    fn update(&self);
}


struct Renderer {
    ecs: Rc<RefCell<Ecs>>,
}

impl System for Renderer {
    fn update(&self) {
        self.ecs.borrow_mut().test();
    }
}

问题似乎出在这条线上:

self.ecs.borrow_mut().test();

这里有什么问题?跟性格有关系吗?还是我需要以其他方式调用函数test

【问题讨论】:

  • 这条信息似乎完全正确:你 borrow_mut() 两次使用相同的 RefCell(通过两个不同的 Rc 指向它的指针),这正是你不能做的事情。

标签: rust borrow-checker borrowing


【解决方案1】:

确实,Renderer 中的 ecs 成员是 ecs 成员的克隆 在Game,即他们都拥有相同的Ecs

当你 borrow_mut() ecs 成员在 Game 然后迭代 元素,你到达Renderer 其中borrow_mut()s 同样Ecs。 这是在运行时检测到的,然后发生恐慌,这是预期的 RefCell 的行为。

如果您在这两种情况下都将borrow_mut() 更改为borrow(), 这不再恐慌,因为多个不可变借用 是允许的。

我不知道这段代码的确切用途,但我不确定 从Renderer 借用Ecs 是个好主意。 我认为内部可变性应该适用于每个 单独存储组件而不是整个Ecs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 2020-12-08
    • 2019-02-10
    • 2021-04-23
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多