I just read about typestates in Rust on Cliff Biffle's blog here: <a href="http://cliffle.com/blog/rust-typestate/#variation-state-types-that-contain-actual-state" rel="nofollow">http://cliffle.com/blog/rust-typestate/#variation-state-type...</a><p>He covers a few additional parts of the typestate pattern, such as isolating data in specific states as well as sharing common implementations across a subset of states.<p>I'd also like to note that typestates also show up in functional programming under Indexed Monads, where a function might take a struct from an initial typestate, unwrap its data, and return a final(likely different) typestate. You can search Indexed Monad for more explanation there. If you work primarily in typescript you can find a production ready implementation of typestate programming here: <a href="https://github.com/DenisFrezzato/hyper-ts" rel="nofollow">https://github.com/DenisFrezzato/hyper-ts</a>
Since this often matters when implementing protocols, there is research about session types and verification. Here is a Rust library for session types: <a href="https://github.com/Munksgaard/session-types" rel="nofollow">https://github.com/Munksgaard/session-types</a><p>I believe both have some overlap.
My gut feeling is that the combination of typestates and stackless coroutines (really: CSP) would make for a kick-ass driver design. It's pretty solid for the toys I've designed for OpenGLES-2-class drivers. My gut feeling is that a lot of the command-buffer shenanigans in Vulkan, Metal, and DX45035+ come from trying to make reasoning about driver development tractable, while also not making the users' lives awful.
In Drone<Hovering>, shouldn't land be:<p><pre><code> fn land(self) -> Drone<Idle> {
Drone::<Idle>::from(self)
}
</code></pre>
instead of:<p><pre><code> fn land(self) -> Drone<Idle> {
Drone::<Idle>::new()
}
</code></pre>
Otherwise the position assertions in drone_flies fail, because it's looking at the position of a brand new Drone<Idle>, rather than one based on the position you just flew to.<p>Edit:<p>Yes it should. [1]<p>[1] <a href="https://github.com/rustype/drone/blob/main/src/drone.rs#L53" rel="nofollow">https://github.com/rustype/drone/blob/main/src/drone.rs#L53</a>
Typestates are an excellent way to provide stronger compile time guarantees, and I wish I saw them more in the wild (I have used them myself when appropriate, though I was unaware of the terminology).<p>However, the article mentions:<p>The attentive reader may have noticed that the consumption and conversion of self into other types implies the values are moved (and in some cases, copied) around.<p>This is untrue; those moves will definitely be optimized away and the typestates will end up being zero cost.
I wonder if it would be a feasible to have some sort of internal compile-time variable in each binding that could make compile-time states not have to use hacky methods like this one.<p>Essentially, instead of the compile-time value attached to a binding only being a type (with generics, optionally), it could also have a regular Rust value attached to it.
This is the feature I most want in every language I use. The main usecase is having 'initialized' / 'ready' / 'destroying' states for objects, which tends to be useful in all kinds of gluecode in lots of settings.
This approach would be a great addition to the AWS CDK. I was trying that out recently and, without constantly referring back to the AWS console or to the docs, it feels like flying blind.
Note that you can do something like Typestates in Java using static inner classes that have no public constructors, though undoubtedly there are advantages to having first class language support. Behold:<p><pre><code> Scanner.OpenScanner sOpen = Scanner.open(/*some source*/);
//do some processing
Scanner.ClosedScanner sClosed = sOpen.close();
sClosed.nextLine() //type error
</code></pre>
I sometimes do this in combination with the Builder pattern. This "typesafe builder" allows for a fluent API that guides the user as to its use.<p>The point is, you can still use types to represent states.