carpdan
carpdan

Reputation: 127

Make Box<Self> function parameter mutable

I've got this code snippet (playground link) where I'm basically trying to change a trait implementation to allow a state change for the struct it's applied to.

The current method signature is:

fn approve(self: Box<Self>) -> Box<dyn State>

, but I need to make it into something like

fn approve(&mut self: Box<Self>) -> Box<dyn State>

This doesn't compile. I've yet to see a Rust &mut self parameter definition along with a type, though I'm not sure why that would be an issue.

If I try:

fn approve(&mut self) -> Box<dyn State>

I get other compile-time errors when I try to return an unmodified self from the method.


For a little bit more context (before checking the playground), here are some relevant code bits:

trait State {
    fn approve(self: Box<Self>) -> Box<dyn State>;
}

struct Draft {
    approve_count: u8,
}

impl State for Draft {
    fn approve(self: Box<Self>) -> Box<dyn State> {
        // self.approve_count += 1;
        if self.approve_count == 2 {
            Box::new(Approved {})
        } else {
            self
        }
    }
}

struct Approved {}

impl State for Approved { ... }

What I would like to do is be able to uncomment the self.approve_count += 1; line and have it work.

Upvotes: 1

Views: 582

Answers (1)

user4815162342
user4815162342

Reputation: 155246

The correct syntax for a mutable reference is:

fn approve(self: &mut Box<Self>)

...but then you won't be able to return self as Box<dyn State> because you're only holding a reference to self.

If all you need is for self.approve_count += 1 to work, you don't need to switch to &mut self, you can simply declare mut self: Box<Self>:

impl State for Draft {
    fn approve(mut self: Box<Self>) -> Box<dyn State> {
        self.approve_count += 1;
        if self.approve_count == 2 {
            Box::new(Approved {})
        } else {
            self
        }
    }
    ...
}

Playground

That code is a bit suspect in that it modifies self.approved_count even in the case where the function returns a completely new Approved instance (and discards the just incremented value), but that may be fixed by moving the increment into the else clause and adjusting the test as appropriate.

Upvotes: 3

Related Questions