A delegate with return type ref immutable(T) can be used to reassign an immutable(T) as follows: alias DGm = ref int delegate() @safe; alias DGi = ref immutable(int) delegate() @safe; @safe void f() { immutable int i = 0; DGi dgi = ref() => i; DGm[] dgms = [ dgi ]; // why? dgms[0]() = 1; assert(i == 1); // fails, because optimization } @safe void g() { DGm[] dgms; foreach (immutable int i; [0]) { assert(i == 0); // just to be sure DGi dgi = ref() => i; dgms ~= dgi; // why? dgms[0]() = 1; assert(i == 1); // passes, meaning immutable i was changed } } The lines marked with // why? should be rejected by the type system.
This reveals a bug in the covariant return checks when ref returns are involved.
@WalterBright created dlang/dmd pull request #13722 "fix Issue 21546 - covariant return checks for functions wrong if retu…" fixing this issue: - fix Issue 21546 - covariant return checks for functions wrong if returning by ref https://github.com/dlang/dmd/pull/13722
dlang/dmd pull request #13722 "fix Issue 21546 - covariant return checks for functions wrong if retu…" was merged into master: - ddbf02545c73a06bf4db1c0d32aa10b186806e22 by Walter Bright: fix Issue 21546 - covariant return checks for functions wrong if returning by ref https://github.com/dlang/dmd/pull/13722