We have this cool feature in D where if you try take the address of a function, and the compiler can't prove that it doesn't escape where the actual stack frame is, it allocates the stack frame on the GC, and then it becomes a "closure".
Why can't we just do this in @safe
code whenever it has the same problem? Consider this code snippet:
void bar(int[]) @safe;
void foo() @safe
{
int[5] arr;
bar(arr[]);
}
Currently, without DIP1000 enabled, this compiles, and if bar
squirrels away the array, you have a memory issue.
With DIP1000, this becomes an error, the compiler yells at you to put scope on the bar parameter (and then you can't squirrel it away).
But what if instead, with DIP1000 seeing that, it just says now we have a closure situation, and allocates foo
's frame on the heap.
A sufficiently smart optimizer might be able to detect that actually bar
doesn't squirrel it away, and will still allocate on the stack.
If you want to ensure this doesn't happen, just like with other closures, you annotate with @nogc. And then you can have suggestions about putting scope on bar
's parameter.
This gives us safe code that may not perform as expected, but at least it is safe. And it doesn't spew endless errors to the user. Consider that there are already so many cases where closures are allocated, with std.algorithm and lambdas, and mostly nobody bats an eye.
Just another possible idea for debate.
-Steve