You can do this in almost any typed language that lets you consume things. Whether you should is another matter.
One problem is where to put your state-specific type info when you're not using it. When you're a thread and your state information is tied to where control is, this is fine. When you're an object which gets called with events, where do you keep this type-specific info? Something like a variant record with all the possible states?
Is the support for "consuming things" really common, though? C++ supports move semantics, invalidating the older copies of the objects (and still does disallow uses statically), but for example, Java has everything behind a pointer, and keeping a reference to the older states would keep the states around. Java would need a runtime-check too, so the type system wouldn't really help that much.
I think it's especially the linear types (or "affine", which is the Rust's variety of almost-linear types) that allows for this kind of statically-checked state machines.
I don't think C++ can statically constrain use after move. A moved value is considered valid, but unspecified. It is entirely possible to use the value after moving it, though maybe there's a warning?
Using Unique Ptr it's a bit hard IIRC (it's been 2 years since I've written C++) but still possible.
One problem is where to put your state-specific type info when you're not using it. When you're a thread and your state information is tied to where control is, this is fine. When you're an object which gets called with events, where do you keep this type-specific info? Something like a variant record with all the possible states?