How to implement TypeState instead of enums for
⚓ Rust 📅 2026-06-17 👤 surdeus 👁️ 4Hey all,
How can you implement the typestate pattern with generic types instead of an enum for a linked list?
Would this have any performance impact?
Here is some minimal example:
enum EnumVariant {
A,
B,
}
impl EnumVariant {
/// abstract example for the function that changes the Enum Variant
pub fn change(&mut self) {
if let EnumVariant::A = self {
*self = EnumVariant::B
}
}
/// abstract example for functions that depend on the Enum
pub fn do_something(&self) {
match self {
Self::A => println!("a"),
Self::B => println!("b"),
}
}
pub fn do_something_for_a(&self) {
if let Self::A = self {
println!("a only")
}
}
}
/// master struct that owns many of these enums
struct MasterStructEnumVariant {
vec: Vec<EnumVariant>,
}
impl MasterStructEnumVariant {
pub fn change(&mut self) {
self.vec.iter_mut().for_each(|e| e.change());
}
}
For the real example the do_something* functions all boilerplate code.. The MasterStructEnumVariant contains a vector of these enums and in the real example, EnumVariant::B will again contain a vector to other MasterStructEnumVariant.
How would it be possible to change this to a typestate pattern?
this would directly eliminate the boilerplate code for those individual functions...
struct StructA;
struct StructB;
struct TypeStateVariant<T> {
val: T,
}
impl TypeStateVariant<StructA> {
pub fn change(&mut self) {
// how to correctly specify the types?
*self = StructB;
}
}
struct MasterStructTypeStateVariant<T> {
vec: Vec<TypeStateVariant<T>>,
}
impl MasterStructTypeStateVariant<StructA> {
pub fn change(&mut self) {
// this is also changing the generic type of MasterStructTypeStateVariant
self.vec.iter_mut().for_each(|e| e.change());
}
// function definitions become easier :-)
pub fn do_something(&self) {
println!("a")
}
// this becomes easily possible :-)
pub fn do_something_for_a(&self) {
println!("a only")
}
}
impl MasterStructTypeStateVariant<StructB> {
pub fn do_something(&self) {
println!("b")
}
}
but this is raising
error[E0308]: mismatched types
--> src\mastermind\mastermind_solver.rs:50:21
|
50 | *self = StructB;
| ----- ^^^^^^^ expected `TypeStateVariant<StructA>`, found `StructB`
| |
| expected due to the type of this binding
|
= note: expected struct `TypeStateVariant<StructA>`
found struct `StructB`
It would be possible to do something like
impl TypeStateVariant<StructA> {
pub fn change(mut self) -> TypeStateVariant<StructB> {
// how to correctly specify the types?
TypeStateVariant { val: StructB }
}
}
impl MasterStructTypeStateVariant<StructA> {
pub fn change(&mut self) {
self.vec = self.vec.drain().map(|e| e.change());
}
}
which is just shifting this issue one level up.
error[E0308]: mismatched types
--> src\mastermind\mastermind_solver.rs:65:24
|
65 | self.vec = self.vec.drain().map(|e| e.change());
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec<TypeStateVariant<StructA>>`, found `Map<Drain<'_, ...>, ...>`
| |
| expected due to the type of this binding
|
= note: expected struct `Vec<TypeStateVariant<StructA>>`
found struct `std::iter::Map<std::vec::Drain<'_, TypeStateVariant<StructA>>, {closure@src\mastermind\mastermind_solver.rs:65:45: 65:48}>`
Is there a better way than creating a function that consumes MasterStructTypeStateVariant and re-creates one with the other type?
...that would totally blow up my use case and not bring any benefit over the enums...
2 posts - 2 participants
🏷️ Rust_feed