Comment #0 by default_357-line — 2018-04-06T15:13:26Z
Consider the following code:
int delegate() @safe foo(scope int delegate() @safe dg) @safe
{
return { return dg(); };
}
int delegate() @safe bar() @safe
{
int k = 5;
return foo({ return k; });
}
void main() @safe
{
writefln("%s", bar()());
}
The writefln outputs random noise because k is out of scope.
Doesn't seem very safe...
Probably foo should not have been allowed to allocate a closure that captured a scope delegate parameter.
Comment #1 by nick — 2018-04-21T13:05:48Z
Closures don't seem to be checked for scope pointers at all:
@safe:
void delegate() foo(ref int a) {
return { a++; };
}
void delegate() bar() {
int a;
return foo(a); // leaking reference to `a`
}
Comment #2 by andy-hanson — 2022-12-06T06:03:21Z
I think is a similar bug:
```
@safe:
import std.stdio : writeln;
void main() {
int* x = escape();
writeln("x is ", *x); // x is 1
*x = 5;
escape();
writeln("x is ", *x); // x is 1
}
pure @nogc nothrow:
int* escape() {
int* res;
callbackWithPointer([1, 2, 3], (int* i) { res = i; });
return res;
}
void callbackWithPointer(T)(scope T[] a, scope void delegate(T*) @safe @nogc pure nothrow f) {
f(&a[0]);
}
```
In this case a `pure` function `escape` appears to return a pointer to global state.
`f(&a[0])` probably shouldn't be allowed. The delegate expects a `T*` but gets a `scope T*`.
Comment #3 by robert.schadek — 2024-12-13T18:58:15Z