Moinonime
Moinonime

Reputation: 304

Having a child modify its parent

I want to have a child struct modify its parent struct. Example:

// Problem: Having a struct's field modify the struct in which the field is.

// MUST NOT be copyable nor clonable
struct Updatee {
    value: u64,
    updater: Updater
}

impl Updatee {
    fn update(&mut self) {
        // ERROR: cannot borrow `*self` as mutable more than once at a time
        self.updater.update(self);
    }
}

// MUST NOT be copyable nor clonable
struct Updater {
    value: u64
}

impl Updater {
    fn update(&mut self, updatee: &mut Updatee) {
        self.value = self.value + 1;
        updatee.value = self.value;
    }
}

fn main() {
    let updater = Updater { value: 0 };
    let updatee = Updatee { value: 0, updater: updater };

    updatee.update();
    updatee.update();

    assert_eq!(2, updatee.value);
}

I'm sure it can be done with unsafe blocks, but is there an alternative?
Perhaps my code is not idiomatic?

Upvotes: 1

Views: 233

Answers (1)

wingedsubmariner
wingedsubmariner

Reputation: 13667

The reason you are getting the "already borrowed" error is because you are trying to pass the Updater to its update method twice, once as self, and once embedded inside of updatee. For memory safety reasons, Rust doesn't allow that.

The simplest solution would be to pass to update a reference to the field in Updatee that needs to be updated rather than the entire Updatee:

impl Updater {
    fn update(&mut self, updatee_value: &mut u64) {
        self.value = self.value + 1;
        *updatee_value = self.value;
    }
}

If multiple fields need to be updated, Updatee could be transformed into a wrapper around the Updater and another struct that holds the fields with the actual data, which could be safely passed to update.

Upvotes: 4

Related Questions