Reputation: 513
I'm trying to write a simple code which generates elements based on a random number generator, for which I have a working code here. Now I wanted to add a reference from each struct to the next in the list. The basic idea is that each struct has a state and an optional reference to another struct with the same lifetime.
#[derive(Copy, Clone, Debug)]
enum MyState
{
On,
Off
}
#[derive(Copy, Clone, Debug)]
struct MyStruct<'a>
{
state: MyState,
next_struct : Option<&'a MyStruct<'a>>,
}
The generic lifetime parameter 'a
is a new addition to basically mark the fact that all structs have the same lifespan.
Then I have a simple associated function creating random structs with no reference, but now my impl
block must also have the generic lifetime parameter.
// 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}
}
}
Finally I'm trying to generate my elements in a loop
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);
}
The full code is here. While the first version worked as expected, the second version fails to compile with
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
Looking at similar questions most of them deal with self references, which seems to be more complicated than what I'm doing here, since I'm passing an unrelated object just for one function call, and it appears to be burrowed for longer..
I tried adding a generic lifetime 'b
to the random method, which is then used only for the RNG mutable, but this does not work either. Why would adding a generic lifetime parameter that is not even used in the signature of the function changes the borrowing behaviour? What is the correct way to write this?
Upvotes: 0
Views: 447
Reputation: 60457
Here's a working version of your function (playground):
impl<'a> MyStruct<'a>
{
fn random(r: &mut RandomGenerator) -> MyStruct<'a>
{ // ^^^^
This is due to lifetime elision:
If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.
Since you didn't annotate the lifetime tied to MyStruct
, the compiler inferred it must be linked to the lifetime of r
.
Upvotes: 2