[Issue 16193] opApply() doesn't heap allocate closure

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Thu Jun 23 06:36:26 PDT 2016


https://issues.dlang.org/show_bug.cgi?id=16193

Steven Schveighoffer <schveiguy at yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
                 CC|                            |schveiguy at yahoo.com
           Hardware|x86_64                      |All
                 OS|Linux                       |All
           Severity|normal                      |regression

--- Comment #3 from Steven Schveighoffer <schveiguy at yahoo.com> ---
(In reply to Marc Schütz from comment #0)
> I'm deliberately using separate compilation here to
> make sure that the compiler has no way to infer that the closure doesn't
> escape.

Separate compilation doesn't imply anything. The compiler can see all the
source for opApply, so it could potentially make the decision that it doesn't
escape.

To prove the compiler is making this optimizing assumption, actually *do*
escape the delegate, and see what happens. When I do this, it actually still
does not create a closure:

// yy.d:
module yy;

struct S {
    int delegate(int) escaped;
    int opApply(int delegate(int) dg) {
        escaped = dg;
        foreach(i; 1 .. 10) {
            int result = dg(i);
            if(result) return result;
        }
        return 0;
    }
}

// xx.d:
import yy;
import std.stdio;

int* px, py;
S s;

int foo() {
    int x = 0, y = 0;
    foreach(i; s) {
        px = &x; py = &y;
        y++;
        writeln("y = ", y);
    }
    return y;
}

void main() {
    writeln(foo());
    int z = 0;
    int *b = new int;
    writeln("&x = ", px, " &y = ", py, " &z = ", &z, " b = ", b);
    s.escaped(0);
}

output (purposely not using separate compilation to prove this has nothing to
do with it):
# dmd xx.d yy.d
# ./xx
y = 1
y = 2
y = 3
y = 4
y = 5
y = 6
y = 7
y = 8
y = 9
9
&x = 7FFF5F29E8E8 &y = 7FFF5F29E8EC &z = 7FFF5F29E920 b = 100C70000
y = 32768

Note the difference in address between the stack variables and the obvious heap
variable. And note the invalid value for y for the escaped call since foo has
gone out of scope.

BTW, tested on a Mac.

This is just a straight-up wrong-code bug. I'm expecting this is also a
regression, but I'm too lazy to find the version where this properly worked :)
However, I do know that dmd at one point ALWAYS allocated a closure, so this
must have worked at some point.

--


More information about the Digitalmars-d-bugs mailing list