【问题标题】:Borrow mutable reference in an impl block with generic lifetime parameter在具有通用生命周期参数的 impl 块中借用可变引用
【发布时间】:2021-08-12 00:25:28
【问题描述】:

我正在尝试编写一个基于随机数生成器生成元素的简单代码,为此我有一个工作代码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 可变,但这也不起作用。为什么添加一个甚至没有在函数签名中使用的通用生命周期参数会改变借用行为?正确的写法是什么?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

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

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

    这是由于lifetime elision:

    如果只有一个输入生命周期位置(是否省略),则该生命周期将分配给所有省略的输出生命周期。

    由于您没有注释与MyStruct 相关的生命周期,编译器推断它必须与r 的生命周期相关联。

    【讨论】:

    • 正是我所缺少的。谢谢!我没有考虑查看返回值的生命周期...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    相关资源
    最近更新 更多