Same approach can be found in use in Clojure. The immutable data structures in Clojure - list, map and vector - have their "transient" counterparts which are mutable. The Clojure reference about transient urges to use them only in the code which cannot be seen by "any other code".
There are guards against leaking transients in client code:
The usual function which work on the immutable data structures don't work on transients. Calling them will throw an exception.
The transients are bound to the thread they are created in. Modifying them from any other thread will throw an exception.
The clojure.core code itself uses a lot of transients behind the scenes.
The main benefit of using transients is the massive speed-up they provide.
So the tightly controlled use of mutable state seems to be OK in the functional languages.