I'm not familiar with the type system of Rust but it seems like a really nice language.
Ofc a type system that helps you deal with mutable data responsibly goes a looong way to alleviate the problem but it's not a guarantee. And often times such a type system comes with weird and unexpected quirks. Here are some examples from C#:
For example "readonly" is not immutable, it's a compile time guarantee that a value can only be assigned in the constructor of a type and to that instance of the type only.
This means that for type Foo with readonly int bar, you can have a constructor Foo(...) : this(...) and the value of bar is mutable in the context of those constructors. For most intents and purposes however, the "readonly" only field however acts immutable enough to give a reasonable degree of immutability.
The you have something like private setter functions. They go a long way to guarantee encapsulation of state. But there's no compile time guarantee that an instance of Bar int baz { get; private set; } won't mutate the baz value of any other Bar instance. In-fact, it's a common misconception that private modifiers make something private to the instance, whereas it's only a compile time guarantee that it's not visible to any other type.
Furthermore, private modifiers don't actually prevent anything from actually utilizing it in runtime. You can simply use reflection or other techniques and do what you will.
Then you can do other weaker forms of type-checking "immutability", for example only exposing getter functions in a IFooReader interface.
These things all help alleviate "dark mutability" to different degrees but the underlying values are still mutable. I guess the point I'm trying to make is, yes, it massively helps to have a type system that guarantees encapsulation and immutability to different degrees. The caveat is that we are still at the mercy of that type system and the way it enforces immutability is often non-obvious and less immutable than one might expect.