In a real project, I have a structure that I need to double buffer, since I can't drop it until the next iteration of a loop. This is complicated by the fact that I can't move it since it's self-referential. The example below shows the exact problem without the complicated self-referential structs.
I have 2 "immovable" objects a_1
and a_2
. I take fat mutable references to them with the Ar
type. I want to create and operate on the Ar
type for the current iteration before Drop-ing the Ar
from the previous iteration. In the below example, I try to wrap the Ar
in an Option
that I save from iteration to iteration, _defer_drop
. This extends the lifetime of the Ar
to 2 iterations, which is what I want, but it prevents the borrow checker from seeing that the borrows of a_1
and a_2
last 2 iterations, yet don't overlap with themselves since they are only borrowed once every 2 iterations.
Has anyone else experienced an issue like this and have any tips?
// I want this to print:
//
// Iteration 1
// Create 1
// Iteration 2
// Create 2
// Drop 1 1
// Iteration 3
// Create 1
// Drop 2 1
// Done
// Drop 1 2
struct A{x: u32, count: u32}
struct Ar<'a>{a: &'a mut A}
impl<'a> Drop for Ar<'a> {
fn drop(&mut self) {
// Example to mutate A on Drop
self.a.count += 1;
println!(" Drop {}: {}", &self.a.x, &self.a.count);
}
}
fn main() {
let mut a_1 = A{x: 1, count: 0};
let mut a_2 = A{x: 2, count: 0};
let mut _defer_drop: Option<Ar> = None;
let mut one = true;
for i in 1..3 {
println!("Iteration {}", i);
if one {
let ar = Ar{a: &mut a_1};
println!(" Create {}", &ar.a.x);
_defer_drop = Some(ar);
} else {
let ar = Ar{a: &mut a_2};
println!(" Create {}", &ar.a.x);
_defer_drop = Some(ar);
}
one = !one;
}
println!("Done");
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `a_1` as mutable more than once at a time
--> src/main.rs:31:28
|
31 | let ar = Ar{a: &mut a_1};
| ^^^^^^^^ mutable borrow starts here in previous iteration of loop
error[E0499]: cannot borrow `a_2` as mutable more than once at a time
--> src/main.rs:35:28
|
35 | let ar = Ar{a: &mut a_2};
| ^^^^^^^^ mutable borrow starts here in previous iteration of loop
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0499`.
error: Could not compile `playground`.
To learn more, run the command again with --verbose.