Jump to page: 1 2
Thread overview
[Issue 21912] Invalid stack closure when calling delegate inside lambda
May 10, 2021
Sebastiaan Koppe
May 12, 2021
Dennis
May 14, 2021
Sebastiaan Koppe
May 14, 2021
Dennis
May 15, 2021
Sebastiaan Koppe
May 15, 2021
Dennis
May 16, 2021
Ketmar Dark
[Issue 21912] delegate assigned to return scope variable needs closure
Jul 15, 2021
Dennis
Jul 15, 2021
Dlang Bot
Jul 22, 2021
Dlang Bot
Aug 03, 2021
Dlang Bot
May 10, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

Sebastiaan Koppe <mail@skoppe.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mail@skoppe.eu

--- Comment #1 from Sebastiaan Koppe <mail@skoppe.eu> ---
The above is a reproduction of a problem I have seen occur several times now.

It always involves a delegate that refers to a parameter. D is supposed to move the parameter to the heap, creating a closure. But as you can see above, in more complex cases it produces garbage.

--
May 10, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

moonlightsentinel@disroot.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |moonlightsentinel@disroot.o
                   |                            |rg

--- Comment #2 from moonlightsentinel@disroot.org ---
Slightly reduced:

@safe:

auto foo(DG)(DG dg, int p) {
    return () => dg(p);
}

auto bla(int i) {
    return foo((int p)=>i*p, 66);
}

void main() {
    assert(bla(5)() == 330);
}

=====================================

Only requires -dip1000 which probably hints at invalid scope inference.

--
May 10, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

--- Comment #3 from moonlightsentinel@disroot.org ---
Even smaller:

=================================
DG foo(DG)(DG dg) {
    return dg;
}

auto bla(int i) {
    return foo(() => i);
}

void main() {
    assert(bla(5)() == 5);
}
=================================

--
May 12, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |dkorpel@live.nl
         Resolution|---                         |DUPLICATE

--- Comment #4 from Dennis <dkorpel@live.nl> ---
This has to do with pure bypassing scope checks:

```
int delegate() pure foo(int delegate() pure dg) pure {
    return dg;
}

int delegate() bla(int i) pure {
    return foo(() => i);
}

void main() {
    assert(bla(5)() == 5);
}
```

*** This issue has been marked as a duplicate of issue 20150 ***

--
May 14, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

--- Comment #5 from Sebastiaan Koppe <mail@skoppe.eu> ---
Could you explain what that has to do with the compiler deciding not to allocate the closure?

--
May 14, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

--- Comment #6 from Dennis <dkorpel@live.nl> ---
(In reply to Sebastiaan Koppe from comment #5)
> Could you explain what that has to do with the compiler deciding not to allocate the closure?

The closure is not allocated because parameter `dg` of `foo` is inferred
`scope`.
`dg` is inferred `scope` because `foo` is inferred (or annotated) `pure`.
The faulty logic that `pure implies scope` is described in the linked issue.

See also the forum post I made about it: https://forum.dlang.org/post/jnkdcngzytgtobihzggj@forum.dlang.org

--
May 15, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

--- Comment #7 from Sebastiaan Koppe <mail@skoppe.eu> ---
I read the post, and it sure looks plausible, I just don't understand it.

If this has to do with "pure bypassing scope checks", then making one of the above examples un-pure would solve it. Although it does work with your reduced case, not with the ones where foo has a DG template parameter.

That still crashes:

```
void unpure() @trusted { static int g; g = 5; }

DG foo(DG)(DG dg) {
    unpure();
    return dg;
}

auto bla(int i) {
    return foo((){ unpure(); return i;});
}

void main() {
    pragma(msg, typeof(bla)); // @safe int delegate() @safe(int i)
    assert(bla(5)() == 5); // Assertion failure
}
```

What does work though, is to assign the delegate to a variable first. This compiles (also with the other DG template examples):

```
int delegate() pure foo(int delegate() pure dg) pure {
    return dg;
}

int delegate() bla(int i) pure {
    auto dg = () => i;
    return foo(dg);
}

void main() {
    assert(bla(5)() == 5); // Pass!
}
```

--
May 15, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|DUPLICATE                   |---

--- Comment #8 from Dennis <dkorpel@live.nl> ---
(In reply to Sebastiaan Koppe from comment #7)
> If this has to do with "pure bypassing scope checks", then making one of the above examples un-pure would solve it. Although it does work with your reduced case, not with the ones where foo has a DG template parameter.

You're right, it turns out there is another issue at play. Reduced to explicit attributes:

```
int delegate() foo(return int delegate() dg) {
    return dg;
}

int delegate() bla(int i) {
    return foo(() => i);
}

void main() {
    assert(bla(5)() == 5);
}
```

Since () => i is assigned to a `return` parameter, the expression `foo(() =>
i)` should be `scope` and cannot be returned from `bla` without allocating a
closure with i on the heap.

I quickly looked at the existing dip1000 issues but couldn't find something similar enough, so let's re-open it.

--
May 16, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

Ketmar Dark <ketmar@ketmar.no-ip.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ketmar@ketmar.no-ip.org

--
July 15, 2021
https://issues.dlang.org/show_bug.cgi?id=21912

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Invalid stack closure when  |delegate assigned to return
                   |calling delegate inside     |scope variable needs
                   |lambda                      |closure

--
« First   ‹ Prev
1 2