Enums, state machines, and ownership


#1

So I’d like to use enums to model state in a state machine. I’m having problems when it comes to ownership, though. Here’s what I’m basically trying to do: https://gist.github.com/mmlinford/c99655a37391ae7bc7fc5da39e73a75b

But of course I get:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:28:28
   |
28 |         self.state = match self.state {
   |                            ^^^^ cannot move out of borrowed content
29 |             State::A(my_thing_a) => {
   |                      ---------- hint: to prevent move, use `ref my_thing_a` or `ref mut my_thing_a`
...
33 |             State::B(my_thing_b) => {
   |                      ---------- ...and here (use `ref my_thing_b` or `ref mut my_thing_b`)

I’m able to sort of get what I want by putting the state field in an Option, then take()ing the content out, doing the operation that consumes it, then putting it back in the Option: https://gist.github.com/mmlinford/ead5d94994bc980652aeff0dfa03626c

This seems inefficient though, since it’s now in an Option and that take() call must take time, right? Is there a better way to achieve what I want?


#2

Yeah, using Option + take() is a typical way to achieve this in the way you want (or std::mem::replace self with a dummy state, which is essentially the same thing). The take() is going to be pretty cheap so I wouldn’t worry about the performance implications.

Another approach entirely is to use an impl technique called session types (aka type state): playground. This is a bit more involved but is actually safer at compile time.


#3

Cool, that looks like what I saw at https://hoverbear.org/2016/10/12/rust-state-machine-pattern/ . I’m glad that what I’m doing sounds like a pretty standard way of doing it. I was just worried that there was some way to trick the borrow checker that I was missing.

And thanks for another great response, @vitalyd


#4

I was just fishing for a link to that blog! :slight_smile: It’s a much nicer take on this than my few sentences above :slight_smile:


#5

It’s also a bigger drain on my too-short attention span :wink: