Rust 有哪些选项可用于管理错误“;不能将“*self”作为可变/不可变的借用;?

Rust 有哪些选项可用于管理错误“;不能将“*self”作为可变/不可变的借用;?,rust,borrow-checker,borrowing,Rust,Borrow Checker,Borrowing,这个问题不是关于编译器为什么会给出这些错误——我想我理解这一点。这个问题是关于如何管理可变路径上的情况,同时希望能够调用其他函数 这是我试图做的事情的简化。我在World中有很多Foos,我需要根据World中的其他数据进行更新。我希望能够调用World中的几个私有函数 pub struct Foo { id: i32, //... } pub struct Bar { //... } pub struct World { foos: Vec<Foo&g

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

这是我试图做的事情的简化。我在
World
中有很多
Foo
s,我需要根据
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();
}
pub struct Foo{
id:i32,
//...
}
酒吧结构酒吧{
//...
}
酒吧结构世界{
foos:Vec,
酒吧:Vec,
//...
}
impl世界{
pub fn create()->World{
世界{
foos:Vec::new(),
条形图:Vec::new(),
}
}
发布fn更新(&mut self){
对于self.get_foos_mut()中的foo{
//错误[E0XXX]:无法将“*self”借用为可变/可替换。。。
让_bar=self.get _bar _给定_foo(foo);
//基于bar和其他世界事物调用其他世界函数来改变foo。。。
//...
}
}
//应该多次调用的一些有用的实用函数
//来自世界各地。。。
fn get_foos_mut(&mut self)->&mut[Foo]{
//基于foos或使用自身数据的任何其他计算选择切片间隔。。。
&mut self.foos[…]
}
fn获取\u bar\u给定\u foo(&self,foo:&foo)->&bar{
//选择基于foo的条形图或使用自身数据的任何其他计算。。。
&self.bar[foo.id as usize]
}
//其他的实用程序函数抽象了我想要的操作序列
//要在更新路径上使用。。。
}
fn main(){
让mut world=world::create();
world.update();
}
你也可以

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

由于我不想克隆所有数据,我可以想出三种解决方案。我试过1号和2号,两个都有效

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

  • 创建接收所需引用的函数。无需再次借用
    self
    。可以删除函数
    World::get_foos_mut(&mut self)->&mut[Foo]
    ,并在
    World
    fn World_get_foos_mut(foos:&mut Vec)->&mut[Foo]
    上的代码显示了此解决方案

  • 创建宏而不是常规函数?因为它们是宏,我怀疑不会涉及任何借用。由于我不熟悉宏,我无法判断这是否有效或如何做到这一点

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

    我真的很沮丧,因为找不到正确的模型来处理这个问题


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

    我推荐的解决方案来自重复项:。有效地将函数移出
    世界
    ,但将它们放入新的结构中,而不是裸露。值得一提的是,所有3种解决方案都是相同的:编译器可以知道结构的字段是不相交的,不会重叠的,但只在单个函数内部。这是经过深思熟虑的,不是将来要“修复”的事情(如副本中所述)。内联代码(使用宏或不使用宏)将其移动到单个函数中,因此编译器可以验证代码。创建细粒度函数在另一个方向上也是如此:如果只传入结构的一部分,则无法修改其他字段。感谢@Shepmaster,感谢您抽出时间指出重复项,并在create_more_structs中向我推荐解决方案。我需要一些时间来完成这一切。不客气。我建议您正确确定核心“变通方法”。我是一个铁锈迷,但我真诚地认为,我在这些情况下创建的较小结构有助于我的代码具有更好的结构。我推荐的解决方案是:从重复中获得。有效地将函数移出
    世界
    ,但将它们放入新的结构中,而不是裸露。值得一提的是,所有3种解决方案都是相同的:编译器可以知道结构的字段是不相交的,不会重叠的,但只在单个函数内部。这是经过深思熟虑的,不是将来要“修复”的事情(如副本中所述)。内联代码(使用宏或不使用宏)将其移动到单个函数中,因此编译器可以验证代码。创建细粒度函数在另一个方向上也是如此:如果只传入结构的一部分,则无法修改其他字段。感谢@Shepmaster,感谢您抽出时间指出重复项,并在create_more_structs中向我推荐解决方案。我需要一些时间来完成这一切。不客气。我建议您正确确定核心“变通方法”。我是一个铁锈迷,但我真的认为我在这些情况下创建的较小结构有助于我的代码具有更好的结构。