April 02, 2013 Re: Using inout in delegate | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer wrote: > On Thu, 28 Mar 2013 04:34:36 -0400, Jacob Carlborg <doob@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 | |||
April 02, 2013 Re: Using inout in delegate | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Kenji Hara | On 2013-04-02 15:03, Kenji Hara wrote: > 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 Then I should probably report this as an issue. -- /Jacob Carlborg | |||
April 02, 2013 Re: Using inout in delegate | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 2013-04-02 16:17, Jacob Carlborg wrote: > Then I should probably report this as an issue. http://d.puremagic.com/issues/show_bug.cgi?id=9859 -- /Jacob Carlborg | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply