I think it hasn't been done because interior mutability is relatively rarely used, and being able to assert immutability in generic code is not actually that useful (and for things like hash map keys you'd need to implement Hash or other traits manually anyway, so you'll probably notice the issue).
In non-generic code, you have to call functions like "borrow()", etc. to access the internally mutable data, so you know it's mutable.
Regarding "fearless concurrency", the Sync trait ensures that, allowing "interior mutability" only if thread-safe (i.e. Mutex or Atomic).
Obviously you can have race conditions between modifications of different Mutex/Atomics, but that's an unavoidable fundamental problem: even transactional systems will have race conditions if you use two separate transactions where you should have used one, and single-threaded event based systems also have them if you "defer" part of the computation improperly.
This caveat is the problem. You lose a ton of properties when you have “interior mutability” (I.e. an object typed as immutable is, in fact, mutable). You probably can’t appreciate the benefit if you haven’t actually used a purely immutable language. Rust touts “fearless concurrency”, but it’s nowhere close to what you can get with Haskell’s guarantee.
> not powerful enough to write safe programs that are as efficient as C programs (since you can't modify memory)
Wrong on both counts. The vast majority of mutable algorithms can be expressed recursively and immutably. Consider haskell’s Vector library. It generates C-equivalent output a lot of the time despite being immutable and much higher level.
The one exception I’ve run into is algorithms that inherently rely a lot on random array writes (like in-place random shuffles), and in this case Haskell has the ST monad for externally pure, referentially transparent mutability that cannot escape into the rest of your program. The fact that haskellers almost never need or want to use ST is very strong evidence that, in fact, you don’t really need mutable semantics at all once you’ve figured out what you’re doing with immutable data.