Thread overview
Nested function bug?
Mar 30, 2012
Ed McCardell
Mar 30, 2012
Walter Bright
Mar 30, 2012
Ed McCardell
Mar 30, 2012
Andrej Mitrovic
Mar 30, 2012
Ed McCardell
March 30, 2012
I ran into a strange and hard-to-describe problem with nested functions closing over the argument to their enclosing function.

When a nested function (A) returns the value of another nested function (B) that returns a parameter of the enclosing function (C), and when (A) is returned from (C), then calling (A) returns an incorrect value if (A) has a parameter of class type (it works when (A) has no class parameters).

The code below demonstrates this (using DMD 2.058, no optimizations). Is this a bug?


auto foo(T)(int val)
{
    int nested()
    {
        return val;
    }

    int escaping(T ignored)
    {
        return nested();
    }

    return &escaping;

//    return &nested; // this works
}

struct Bar {}

class Baz {}

void main()
{
    auto func1 = foo!int(55);
    auto val1 = func1(12);
    assert(val1 == 55); // works fine with integral type

    auto func2 = foo!Bar(55);
    Bar bar;
    auto val2 = func2(bar);
    assert(val2 == 55); // works fine with struct

    auto func3 = foo!Baz(55);
    auto baz = new Baz();
    auto val3 = func3(baz);
    assert(val3 == 55); // fails; val3 is different value on each run
}

March 30, 2012
On 3/30/2012 1:13 PM, Ed McCardell wrote:
>
> I ran into a strange and hard-to-describe problem with nested functions closing
> over the argument to their enclosing function.
>
> When a nested function (A) returns the value of another nested function (B) that
> returns a parameter of the enclosing function (C), and when (A) is returned from
> (C), then calling (A) returns an incorrect value if (A) has a parameter of class
> type (it works when (A) has no class parameters).
>
> The code below demonstrates this (using DMD 2.058, no optimizations). Is this a
> bug?

Looks like one. Please report this to

http://d.puremagic.com/issues/enter_bug.cgi?product=D
March 30, 2012
On 3/30/12, Ed McCardell <edmccard@hotmail.com> wrote:
> The code below demonstrates this (using DMD 2.058, no optimizations). Is
> this a bug?

You mean the result is 55 when you uncomment "return &nested;"? All asserts pass for me when I use that return. Otherwise when using "return &escaping;" I get:

1244764
1244764
4202631

2.058 win32.
March 30, 2012
On 03/30/2012 04:51 PM, Andrej Mitrovic wrote:
> You mean the result is 55 when you uncomment "return&nested;"? All
> asserts pass for me when I use that return. Otherwise when using
> "return&escaping;" I get:
>
> 1244764
> 1244764
> 4202631
>
> 2.058 win32.

On 64-bit linux, the first two asserts always pass using either "return &nested" or "return &escaping". Just checked on 32-bit linux and I see the same behavior you are, with all three asserts failing using "return &escaping".

--Ed
March 30, 2012
On 03/30/2012 04:45 PM, Walter Bright wrote:
> On 3/30/2012 1:13 PM, Ed McCardell wrote:
>> The code below demonstrates this (using DMD 2.058, no optimizations).
>> Is this a
>> bug?
>
> Looks like one. Please report this to
>
> http://d.puremagic.com/issues/enter_bug.cgi?product=D

Done:

http://d.puremagic.com/issues/show_bug.cgi?id=7801