I'm immediately turned off by the entirely gratuitous use of unsafe here. I clicked through to the linked Reddit discussion and I'm not convinced the author has really thought it through. Writing, "pedagogically, that's irrelevant to the post, so I didn't highlight it" misunderstands the pedagogy here.
However, there's some really neat stuff later, so it's wise to grit your teeth and get past it.
In case anyone else had the same reaction, here's an entirely-safe version of the first snippet that you can pretend replaced the original:
// Each state is a unique type
struct Receiving;
struct Sending;
// The state machine is parameterized by the state
struct Channel<State> {
chan: ...,
_state: PhantomData<State>
}
// Methods for the state are uniquely associated with only the state
impl Channel<Receiving> {
// recv consumes ownership, ensuring old state is invalidated
fn recv(mut self) -> (Channel<Sending>, String) {
let Channel { chan, .. } = self;
let msg = chan.recv();
// The state type changes after executing a transition
let next = Channel { chan, _state: PhantomData };
(next, msg)
}
}
impl Channel<Sending> {
fn send(mut self, msg: String) -> Channel<Receiving> {
let Channel { chan, .. } = self;
chan.send(msg);
Channel { chan, _state: PhantomData }
}
}
#[test]
fn channel_test() {
let c: Channel<Sending> = Channel::new();
let c: Channel<Receiving> = c.send("hi");
let (c, msg) = c.recv();
// and so on
}
However, there's some really neat stuff later, so it's wise to grit your teeth and get past it.
In case anyone else had the same reaction, here's an entirely-safe version of the first snippet that you can pretend replaced the original: