是否可以将结构的一部分借用为可变的而其他部分为不可变的?

Kim*_*Kim 7 rust borrow-checker

是否可以将结构的一部分借用为可变的,将另一部分借为不可变的 - 如果结构的字段是私有的。

fn main() {
    let mut ecs = EntityComponentSystem::new();

    for e_id in ecs.get_entities_with_component::<Velocity>().unwrap() {
           let components = ecs.get_mut_components(e_id);
           ...
}

impl EntityComponentSystem {
    ...
    pub fn get_entities_with_component<K: Key>(&self) -> Option<&HashSet<u64>> {
        self.entities_with_components.get(&TypeId::of::<K>())
    }

    pub fn get_mut_components(&mut self, entity_id: u64) -> &mut TypeMap {
        let entity = self.entities.get_mut(&entity_id).unwrap();
        &mut entity.components
    }
}

pub struct EntityComponentSystem {
    entities: HashMap<u64, Entity>,                     <------- I would like to modify this.
    entities_with_components: HashMap<TypeId, HashSet<u64>>,   <---- while reading from this!
}
Run Code Online (Sandbox Code Playgroud)

编译器给了我:

fn main() {
    let mut ecs = EntityComponentSystem::new();

    for e_id in ecs.get_entities_with_component::<Velocity>().unwrap() {
           let components = ecs.get_mut_components(e_id);
           ...
}

impl EntityComponentSystem {
    ...
    pub fn get_entities_with_component<K: Key>(&self) -> Option<&HashSet<u64>> {
        self.entities_with_components.get(&TypeId::of::<K>())
    }

    pub fn get_mut_components(&mut self, entity_id: u64) -> &mut TypeMap {
        let entity = self.entities.get_mut(&entity_id).unwrap();
        &mut entity.components
    }
}

pub struct EntityComponentSystem {
    entities: HashMap<u64, Entity>,                     <------- I would like to modify this.
    entities_with_components: HashMap<TypeId, HashSet<u64>>,   <---- while reading from this!
}
Run Code Online (Sandbox Code Playgroud)

我没有理解的是,在我们基本上返回了字段的一部分之后,&selfin 中的引用get_entities_with_component仍然是借用的entities_with_components

不应该只借那部分吗?有什么办法可以强制执行吗?

Jan*_*ner 10

您只能借用整个结构作为不可变或可变的结构,不存在仅借用部分结构的概念。当这成为问题时,您可以以 a 的形式使用内部可变性RefCell

pub struct EntityComponentSystem {
    entities: RefCell<HashMap<u64, Entity>>,
    entities_with_components: HashMap<TypeId, HashSet<u64>>,
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以借用整个结构作为不可变结构,并借用独立结构的内容RefCell作为可变结构:

pub fn get_mut_components(&self, entity_id: u64) -> &mut TypeMap {
    let mut entities = self.entities.borrow_mut();
    let entity = entities.get_mut(&entity_id).unwrap();
    &mut entity.components
}
Run Code Online (Sandbox Code Playgroud)

  • “你只能借用整个结构作为不可变或可变的,不存在只借用其中一部分的概念。” 迂腐地说,是的。您可以对结构进行部分借用,但这对操作不起作用,因为字段是私有的。这是一个示例:https://play.rust-lang.org/?gist=fcfcca700ba238287063143754e15c97&amp;version=stable (7认同)