D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 18827 - scope delegate literal allocates GC closure
Summary: scope delegate literal allocates GC closure
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 major
Assignee: No Owner
URL:
Keywords: industry
Depends on:
Blocks:
 
Reported: 2018-05-04 14:56 UTC by Martin Nowak
Modified: 2021-06-02 14:04 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Martin Nowak 2018-05-04 14:56:57 UTC
cat > bug.d << CODE
int func(int delegate(int) dg)
{
    return dg(2);
}

int templ(alias dg)()
{
    return dg(2);
}

void bar()
{
    int a = 3;
    scope dg = (int x) => x * a;
    func(dg); // does not allocate closure, GOOD
    templ!((int x) scope => x * a)(); // does not allocate closure, GOOD
    func((int x) scope => x * a); // does allocate closure, BAD
}
CODE

Passing a delegate literal with scoped context should never allocate a closure, but it does when the delegate is being passed by value.

With DIP1000 escaping of the context within the delegate should be statically forbidden, right now it depends on programming correctness. Still an explicit scope should disable allocations anyhow, though prolly mark the delegates as unsafe.
Comment 1 Dennis 2021-06-02 14:04:28 UTC
It should allocate a closure, since `func` is free to escape the delegate, e.g.:
```
int delegate(int) global;

int func(int delegate(int) dg)
{
    global = dg;
    return dg(2);
}

void bar()
{
    int a = 3;
    scope dg = (int x) => x * a;
    func(dg); // passing scope dg to non-scope parameter makes bar @system
    func((int x) scope => x * a);
}
```

When marking the input delegate of `func` `scope`, it works:
```
@safe:
int func(scope int delegate(int) @safe @nogc dg) @nogc
{
    return dg(2);
}

void bar() @nogc
{
    int a = 3;
    scope dg = (int x) => x * a;
    func(dg);
    func((int x) scope => x * a);
}
```