Rust's affine typing solves precisely this problem as well. Your state change methods consume the previous state variable, making it a compile-time error to access it afterwards. Given code like in the article and assuming connect_unauthenticated takes self by value:
let i1 = socks5_socket();
let i2 = i1.connect_unauthenticated(proxy_addr);
let i3 = i1.connect_tcp(addr);
Rust will complain: error[E0382]: use of moved value: `i1`
|
2 | let i2 = i1.connect_unauthenticated(proxy_addr);
| - value moved here
3 | let i3 = i1.connect_tcp(addr);
| ^ value used here after move
|
= note: move occurs because `i1` has type `socks5_socket`, which does not implement the `Copy` trait