Comment #0 by verylonglogin.reg — 2013-06-30T05:52:06Z
The allocation is done eager but can be lazy:
---
bool noAllocations = false;
extern(C) void* gc_malloc(size_t sz, uint ba = 0);
extern(C) void* _d_allocmemory(size_t sz)
{
assert(!noAllocations); // fails
return gc_malloc(sz);
}
int delegate() del;
void f(int i)
{
if(i)
del = () => i;
}
void main()
{
noAllocations = true;
f(0);
noAllocations = false;
}
---
This hits with pain as one do not expect such behaviour and can e.g. branch out closures in destructors expecting no allocation is done and then get strange InvalidMemoryOperationError-s when GC is collecting.
Comment #1 by clugdbug — 2013-09-19T23:28:25Z
This is a very difficult optimization.
Consider:
void f(int i)
{
if (i)
del = () => i; // (1)
++i; // (2)
}
If you put i on the heap only at (1), then the compiler has trouble generating code at (2) -- is i on the heap, or on the stack?
Another example:
if (cond1())
del = () => i;
if (cond2())
del = () => i*2;
The compiler would then have to generate code to move i onto the heap in two places, and in the second case, it might already be on the heap.
> This hits with pain as one do not expect such behaviour
I think that is inevitable. In some simple cases, the compiler might be able to avoid creating a closure, but it will always be rather conservative.
This isn't wrong code, it's a missed optimization opportunity.
Comment #2 by verylonglogin.reg — 2013-09-20T11:00:46Z
What I'm afraid is inlining. Is it possible that the function allocating closure in `if` branch is inlined and results in the issue?
Comment #3 by robert.schadek — 2024-12-13T18:08:49Z