Reputation: 13
struct Parent<'a> {
inner: Option<&'a mut Object>
}
impl<'a> Parent<'a> {
fn new() -> Parent<'a> {
Parent {
inner: None,
}
}
fn bind(&mut self, obj: &'a mut Object) {
self.inner = Some(obj);
}
fn unbind(&mut self) {
self.inner = None;
}
}
struct Object {
inner: u32,
}
fn main() {
let mut obj = Object { inner: 0 };
let mut parent1 = Parent::new();
let mut parent2 = Parent::new();
parent1.bind(&mut obj);
parent1.unbind();
// parent2.bind(&mut obj);
// ^ error
}
Struct Parent
field must store the Option
:
struct Parent {
inner: Option</* magic */>
}
It is necessary to temporarily block the possibility of working with the object in fn main()
, until you call the .unbind()
Upvotes: 1
Views: 133
Reputation: 43
You could also scope the usage of parent1
. Since once you bind obj
to parent2
, it cannot be used by parent1
anymore:
let mut obj = Object { inner: 0 };
{
let mut parent1 = Parent::new();
parent1.bind(&mut obj);
parent1.unbind();
}
let mut parent2 = Parent::new();
parent2.bind(&mut obj);
Upvotes: 0
Reputation: 31163
It's impossible for the borrow checker to prove this correct at compile-time. But you can use RefCell
to make sure it works at runtime and panics if you do it wrong. Instead of storing a reference to the object in the Parent object, you can store a RefMut
that allows you to modify the object. The bind
function takes a reference to a RefCell
and will panic if the object is already borrowed.
use std::cell::*;
struct Parent<'a> {
inner: Option<RefMut<'a, Object>>,
}
impl<'a> Parent<'a> {
fn new() -> Parent<'a> {
Parent {
inner: None,
}
}
fn bind(&mut self, obj: &'a RefCell<Object>) {
self.inner = Some(obj.borrow_mut());
}
fn unbind(&mut self) {
self.inner = None;
}
}
struct Object {
inner: u32,
}
fn main() {
let obj = RefCell::new(Object { inner: 0 });
let mut parent1 = Parent::new();
parent1.bind(&obj);
parent1.unbind(); // comment this line out and you get a runtime panic
let mut parent2 = Parent::new();
parent2.bind(&obj);
}
Upvotes: 2