在具有通用生命周期参数的 impl 块中借用可变引用

Borrow mutable reference in an impl block with generic lifetime parameter

我正在尝试编写一个简单的代码来生成基于随机数生成器的元素,为此我有一个工作代码 here。现在我想将每个结构的引用添加到列表中的下一个。基本思想是每个结构都有一个状态和一个对另一个具有相同生命周期的结构的可选引用。

#[derive(Copy, Clone, Debug)]
enum MyState
{
    On,
    Off
}

#[derive(Copy, Clone, Debug)]
struct MyStruct<'a>
{
    state: MyState,
    next_struct : Option<&'a MyStruct<'a>>,
}

通用生命周期参数 'a 是一个新增功能,主要用于标记所有结构具有相同生命周期这一事实。

然后我有一个简单的关联函数创建没有引用的随机结构,但现在我的 impl 块还必须具有通用生命周期参数。

// stand-in for replacement struct from rand crate
struct RandomGenerator {
    random_number : f64,
}

impl<'a> MyStruct<'a>
{
    fn random(r : & mut RandomGenerator) -> MyStruct
    {
        if r.random_number > 0.5 {
            r.random_number -= 0.1;
            return MyStruct{state : MyState::On, next_struct : None};
        }
        r.random_number = 1.0 as f64;
        MyStruct{state : MyState::Off, next_struct : None}
    }
}

最后我尝试循环生成我的元素

fn main() {
    let mut grid = Vec::<MyStruct>::new();
    let mut rng  = RandomGenerator{random_number : 0.5};
    for _i in 0..GRID_SIZE*GRID_SIZE // const GRID_SIZE : usize = 10;
    {
            grid.push(MyStruct::random(&mut rng));
    }
    println!("{:#?}", grid);
}

完整代码为here。虽然第一个版本按预期工作,但第二个版本无法编译

error[E0499]: cannot borrow `rng` as mutable more than once at a time
  --> src/main.rs:43:60
   |
43 |             grid.get_mut(i).unwrap().push(MyStruct::random(&mut rng));
   |                                                            ^^^^^^^^ `rng` was mutably borrowed here in the previous iteration of the loop

error: aborting due to previous error

查看类似的问题,其中大部分都涉及自引用,这似乎比我在这里做的更复杂,因为我只是为一个函数调用传递了一个不相关的对象,而且它看起来是挖的时间长了..

我尝试将通用生命周期 'b 添加到随机方法,然后仅用于 RNG 可变,但这也不起作用。为什么添加一个甚至没有在函数签名中使用的通用生命周期参数会改变借用行为?正确的写法是什么?

这是您函数的工作版本 (playground):

impl<'a> MyStruct<'a>
{
    fn random(r: &mut RandomGenerator) -> MyStruct<'a>
    {                                          // ^^^^

这是由于 lifetime elision:

If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.

由于您没有注释绑定到 MyStruct 的生命周期,编译器推断它必须链接到 r 的生命周期。