January 31, 2020
https://issues.dlang.org/show_bug.cgi?id=20551

          Issue ID: 20551
           Summary: In @safe code and using delegates, it's possible to
                    escape references to function frame
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: safe
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: b2.temp@gmx.com

test case, compiled with dmd 2.090.0, -preview=dip25 -preview=dip1000:

---
module runnable;

import std.stdio;

struct LazyStore(T)
{
    T delegate() @safe dg;

    void opAssign(E)(lazy E e) @safe
    {
        dg = cast(typeof(dg)) &e;
    }

    T test() @safe{ return dg(); }
}

static LazyStore!int f;

void main(string[] args) @safe
{
    int x = 1;
    f = x + x + 20 + x * 20;
    writeln(f.test());
}

static void corrupt()
{
    writeln(f.test());
}

static ~this()
{
    corrupt();
}
---

LazyStore keeps a reference to the local variable passed as lazy expression in
its opAssign.
When using it out of the main() frame the result is undefined.

Suggested fix is to disallow taking address of a lazy parameter but only in
@safe code,
since otherwise this trick plesantly works.

--