December 11, 2017
https://issues.dlang.org/show_bug.cgi?id=18058

          Issue ID: 18058
           Summary: @nogc and forwarding lazy argument, particularly with
                    scope
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: shachar@weka.io

Relevant forum thread is at https://forum.dlang.org/thread/p0j3o9$1hhn$1@digitalmars.com

The program:
void func1(scope lazy string msg) @nogc {
}

void func2(scope lazy string msg) @nogc {
    func1(msg);
}

does not compile:
test.d(5): Error: @nogc function 'test.func2' cannot call non-@nogc delegate
'msg'

This is wrong. Since "msg" is never evaluated, the fact that it is not @nogc should not matter (not to mention we should have a syntax where we mandate that a lazy argument be @nogc, but that's another issue).

According to my analysis, there are actually two problems here. The first is that "scope" on lazy is being ignored.

The second problem is that the lowering is overly complicated. Instead of lowering to:

void func1(string delegate() msg) @nogc {
}

void func2(string delegate() msg) @nogc {
    func1(msg);
}

which would work with or without the "scope", it is probably lowered to:
void func1(string delegate() msg) @nogc {
}

void func2(string delegate() msg) @nogc {
    func1( (){ return msg();} );
}

which, if no scope is specified, requires that func2's frame be GCed. Since the first argument is already a delegate, the second wrapping is completely unnecessary.

--