Suppose we define a generic struct, with many fields, representing a type-safe state machine using a phantom type:
struct Foo<State> {
a: A,
b: B,
c: C,
//...
state: PhantomData<State>,
}
We can then write a type-safe state transition:
impl Foo<SourceState> {
fn transition(self, extra: X) -> Foo<DestinationState> {
let Foo {a, b, c, state: _} = self;
// do lots of stuff
Foo { a, b, c, state: PhantomData }
}
}
But we need to awkwardly unpack every field and re-pack in in a different structure.
We could also use mem::transmute, although my understanding is that different monomorphizations of the same struct are not guaranteed to have the same memory layout.
I hoped that Foo { state: PhantomData, ..self } would work; alas, it fails to compile.
Is there any canonical, ergonomic, safe way to write this ?
There is no way to do that in a straight forward manner, because they are 2 different types: that's the whole point of your code, actually. To simplify it, I'd do that in 2 steps, with a generic transition being the 2nd one:
Alternatively, you can abstract the fact that you have a state: