With dmd v2.088.0-rc.1 (and earlier): @safe: int* addr(return ref int b) { return &b; } struct S { int i; } auto s() {return S();} void main(){ //auto p = addr(S().i); // cannot modify constant expression `S(0).i` auto p = addr(s().i); (*p)++; } Here the problem is that p outlives the int passed to addr. I think `return &b` in addr should not be allowed, because the returned pointer can live longer than the argument passed to the `ref int b` parameter. Allowing &b to be returned also makes enhancing D to support @safe smart containers harder than it needs to be, requiring flow analysis - any ref can be turned into a scope pointer which lives longer.
This is with -dip1000.
@WalterBright created dlang/dmd pull request #10945 "fix Issue 20183 - Assigning statement scope of struct literal or temp…" fixing this issue: - fix Issue 20183 - Assigning statement scope of struct literal or temporary to variable with longer lifetime https://github.com/dlang/dmd/pull/10945
The problem is that the lifetime of a struct literal or temporary is only to the end of the expression it appears in. Assigning the address of them to a longer lived variable is not valid.
dlang/dmd pull request #10945 "fix Issue 20183 - Assigning statement scope of struct literal or temp…" was merged into master: - 37a695f4839b2f50d64535640382cb777459585b by Walter Bright: fix Issue 20183 - Assigning statement scope of struct literal or temporary to variable with longer lifetime https://github.com/dlang/dmd/pull/10945