On Thursday, 16 March 2017 at 17:20:10 UTC, Carl Sturtivant wrote:
OK, but if I try to do this,char[2] u; string s = u;
Yeah, that's because `u` is not necessarily unique like a function return value:
char[2] u; char[] mutable = u[]; string s = u[]; char before = s[0]; mutable[0] = 'n'; char after = s[0]; assert(before == after); // fails! because mutable[0] changed it.But, with a function return value, there's no opportunity to insert that sneaky `char[] mutable = u[];` alias, so the compiler is free to assume that it is the only reference and do the immutable thing.
If it returns a value type, the compiler can cast to immutable at any time because it knows there is no chance to insert an alias at all - the function return is the only way to access it.
If it returns a reference type, the compiler can cast to immutable if the function is *strongly* pure, because the purity rules also don't give you an opportunity to sneak a mutable reference out (pure cannot write to stuff outside the return values).
I said *strongly* because the compiler will correctly complain if you try to pass a mutable argument back as the return value. It realizes whomever passed the argument might still have an alias and will not allow the implicit cast:
pure char[] foo(char[] a) { return a; }
char[] lolStillMutable;
string tricky = foo(lolStillMutable); // illegal
