Heheyizi
Heheyizi

Reputation: 13

To temporarily hold the borrowed object

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

Answers (2)

Nikolai Hellwig
Nikolai Hellwig

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

oli_obk
oli_obk

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

Related Questions