Immutable by default is only really possible now that we have gobs of memory though. I'm not even sure it's likely to stay popular: the demands of data processing at scale mean we're all likely to be routinely handling gigantic datasets which we don't want to copy all over the place.
The real problem is just visibility: am I editing a copy of the original? Who else can edit the original? Who's going to?
I'd argue those two questions are what we actually want to know the answer to, and immutability criteria are just an awkward compromise solution.
Immutable by default doesn't mean you have to write your program as a giant copy-aon-write or log-structured architecture. You can still commit all your shared global program state behind a mutex/rwlock crimes when that makes sense. But you can contain write access to that data to the places where it's needed.
And at the function-local level move elision should turn copy-and-modify to in-place modification if the original is no longer used.
"Immutable by default is only really possible now that we have gobs of memory though"
I don't think so, actually. It's just changing the default. A choice to have types like Java's String which are always immutable might drive up memory usage, but just realising that the defaults are wrong and altering the language doesn't impact this at all, instead it makes your programs more explicit about what's actually happening.
LLVM will transform your mutable program into immutable one anyway because otherwise it's much harder if not impossible to write a lot of optimizations or validations.
You can collapse a lot of the additional copies at compile time even for C
That's not really the same thing though - that's a choice of representation for optimization purposes. LLVM won't turn a pointer access into a value copy - it can't, because that would change program behavior.
The distinction here is that in a lot of cases, you really do want to edit data in one location and there's no good reason for it to be copied except that it makes the program easier to reason about (exceptions apply for when things like cache locality considerations come into play).
I seem to recall that in many cases it is in fact permitted for C compiler (probably C++ as well) to turn pointer access into value copy so long as the rather flexible semantics are still kept.
The main saving grace is that usually you're only dealing with register copies...
The real problem is just visibility: am I editing a copy of the original? Who else can edit the original? Who's going to?
I'd argue those two questions are what we actually want to know the answer to, and immutability criteria are just an awkward compromise solution.