On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer
wrote:
On Thu, 28 Mar 2013 04:34:36 -0400, Jacob Carlborg
<d...@me.com> wrote:
The following code fails to compile:
void foo (inout int[] arr)
{
auto dg = {
foreach (i, e ; arr) {}
};
dg();
}
void main ()
{
auto a = [3, 4, 5];
foo(a);
}
Error message:
main.d(9): Error: variable main.foo.__lambda1.__aggr1174 inout
variables can only be declared inside inout functions
main.d(9): Error: variable main.foo.__lambda1.e inout
variables can only be declared inside inout functions
If I remove the delegate everything compiles. Am I doing
something wrong?
Like Timon said, it's a bug in inout design.
I think this is not a hole of inout design. In this case, the
lambda inside foo should capture 'inout' context pointer.
void foo (inout int[] arr)
{
auto dg = {
foreach (i, e ; arr) {}
};
pragma(msg, typeof(dg)); // should print "void delegate()
inout"
dg();
}
I'm assuming the issue is that the compiler is trying to
generate a struct to hold the stack data for foo, and struct
members cannot be inout.
It is true, but in this case, the context which is implicitly
captured by closure is not directly accessible from programmers.
So qualifying it 'inout' is safe.
It is a difficult problem to solve, because inout has two
meanings depending on whether it is a parameter/return or a
local variable. At some point, we need to address this,
because inout has so much potential, but suffers from some
large deficiencies.
And, inout closure cannot escape from enclosing inout function.
auto foo(inout int[] arr)
{
auto dg = (inout int[] a)
{
return arr; // returns captured inout 'arr'
};
return dg; // escape! (should be rejected statically)
}
If compiler does not reject escape...
void main()
{
const int[] a = [3, 4, 5];
auto dg = foo(a);
// typeof(dg) == inout(int[]) delegate(inout(int[]))
int[] b = dg([]);
assert(b.ptr == a.ptr); // type-system breaking!
}
Kenji Hara