有哪些选项可用于管理错误“无法借用* self可变或不可变”?

时间:2019-06-08 01:32:47

标签: rust borrow-checker borrowing

这个问题与编译器为什么会给出这些错误无关-我想我理解这一点。这个问题是关于如何在可变路径上管理情况,同时希望能够调用其他功能。

这是我正在尝试做的简化。 Foo中有很多World,我需要根据World中的其他数据更新它们。我希望能够在World内调用几个私有函数。

pub struct Foo {
    id: i32,
    //...
}

pub struct Bar {
    //...
}

pub struct World {
    foos: Vec<Foo>,
    bars: Vec<Bar>,
    //...
}

impl World {

    pub fn create() -> World {
        World {
            foos: Vec::new(),
            bars: Vec::new(),
        }
    }

    pub fn update(&mut self) {
        for foo in self.get_foos_mut() {
            //error[E0XXX]: cannot borrow `*self` as mutable/imutable ...
            let _bar = self.get_bar_given_foo(foo);
            //alter foo based on bar and other world things calling other world functions...
            //...
        }
    }

    //some useful utility functions that should be called several times
    //from different World places...

    fn get_foos_mut(&mut self) -> &mut [Foo] {
        //select slice interval based on foos or any other calculation using self data...
        &mut self.foos[..]
    }

    fn get_bar_given_foo(&self, foo: &Foo) -> &Bar {
        //select bar based on foo or any other calculation using self data...
        &self.bars[foo.id as usize]
    }

    //other utility functions that abstract e sequence of operations that I would 
    //like to use on the update path...    
}

fn main() {
    let mut world = World::create();
    world.update();
}

您也可以run the code

这看起来非常局限,因为在update函数这样的可变路径上,我无法从self调用任何私有方法。

由于我不想克隆所有数据,因此我想到了三种解决方案。我尝试过1和2都可以。

  1. 内联所有内容。由于此解决方案适用于上面的示例,因此编译错误似乎是由于Rust编译器的限制所致,据我所知:它只是查看函数签名而不是函数的实现。

  2. 创建接收所需内容引用的功能。无需再次借用self。可以删除功能World::get_foos_mut(&mut self) -> &mut [Foo]并在World外部创建一个新函数:fn world_get_foos_mut(foos: &mut Vec<Foo>) -> &mut [Foo] playground上的代码显示了此解决方案。

  3. 创建宏而不是常规函数??由于它们是宏,我怀疑其中不会涉及任何借用。由于我不熟悉宏,因此无法确定它是否有效或如何执行。

我真的需要其他选择,因为我认为解决方案1不可行,解决方案2看起来非常麻烦且脆弱(看起来我可能有相同的问题,但引用World中)。

我对于无法找到正确的模型来处理此问题感到非常沮丧。

Rust编译器将来会尝试分析这些情况吗?

0 个答案:

没有答案