Error sum types do the exact same thing.
> The alternative that the parent said was making all of your state be a union with some kind of error, and making sure all accesses handle the fact the variable might be in a erroneous state.
Which is a non-issue as it is lifted to the type system. The type system will not let you forget about that.
> That is a huge explosion of possible states in your program, and essentially making every invariant weak everywhere.
You get an error state added to a given value, which you also get via exceptions, except implicitly and without notification of the additional state.
Type-safe error values also provide simpler error handling and recovery in many case, because they don't require split-path handling.
> Then FFI, I suppose you mean interfacing with C. Problems that arise when interfacing with other programming languages are orthogonal to a language's ability to be used for system programming.
It very much isn't, part of the system programming workload is to provide reusable components.
> Obviously you wouldn't let an exception propagate through some C code, that's forbidden.
And rarely if every checkable statically, hence unsafe.