digitalmars.D.learn - Using inout in delegate
- Jacob Carlborg (21/21) Mar 28 2013 The following code fails to compile:
- Timon Gehr (2/21) Mar 28 2013 It is a bug / problem with inout's design.
- Steven Schveighoffer (11/30) Mar 28 2013 Like Timon said, it's a bug in inout design.
- Kagamin (2/2) Mar 28 2013 well, closure is effectively a struct, so its fields should be
- Jacob Carlborg (8/17) Mar 28 2013 I had to change to a regular for-loop and declare the element as "const"...
- Maxim Fomin (16/19) Mar 28 2013 This is a foolishness of dmd frontend. It generates names for
- Kagamin (3/4) Mar 29 2013 try to bypass the type system; we just saw the variables are
- Maxim Fomin (2/6) Mar 29 2013 You saw one particular example, the problem is much bigger.
- Kagamin (2/3) Apr 01 2013 What's problem? Try it.
- Maxim Fomin (11/14) Apr 01 2013 ???
- Kenji Hara (35/72) Apr 02 2013 I think this is not a hole of inout design. In this case, the
- Jacob Carlborg (4/43) Apr 02 2013 Then I should probably report this as an issue.
- Jacob Carlborg (4/5) Apr 02 2013 http://d.puremagic.com/issues/show_bug.cgi?id=9859
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? -- /Jacob Carlborg
Mar 28 2013
On 03/28/2013 09:34 AM, Jacob Carlborg 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?It is a bug / problem with inout's design.
Mar 28 2013
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'm not sure what __aggr1174 is, but you can fix the e error by specifying the type for e (or specifying it as const). 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 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. -Steve
Mar 28 2013
well, closure is effectively a struct, so its fields should be properly qualified, e.g. as const.
Mar 28 2013
On 2013-03-28 15:16, Steven Schveighoffer wrote:Like Timon said, it's a bug in inout design. I'm not sure what __aggr1174 is, but you can fix the e error by specifying the type for e (or specifying it as const). 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 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.I had to change to a regular for-loop and declare the element as "const": for (size_t i = 0; i < arr.length; i++) { const e = arr[e]; } -- /Jacob Carlborg
Mar 28 2013
On Thursday, 28 March 2013 at 14:16:27 UTC, Steven Schveighoffer wrote:I'm not sure what __aggr1174 is, but you can fix the e error by specifying the type for e (or specifying it as const). -SteveThis is a foolishness of dmd frontend. It generates names for copies, temporaries, etc. These names are not only visible (a user can receive error messages referring to such names with no idea what are the variables the compiler is talking about) but accessible which allows to do funny nonsense stuff, probably bypassing type system. http://dpaste.dzfl.pl/15d67a77 Dmd is the only compiler I am aware of which makes visible internal stuff and allows to manipulate it. These names are created almost anywhere where there is parameter passing, temporary, foreach loop, a tuple access, a lambda or a delegate literal and in many other cases. Judging by console dump of this stuff when compiling phobos, I come to conclusion that dmd for ages is able to accept enormous amount of invalid code.
Mar 28 2013
On Thursday, 28 March 2013 at 16:34:47 UTC, Maxim Fomin wrote:probably bypassing type system.try to bypass the type system; we just saw the variables are typechecked.
Mar 29 2013
On Friday, 29 March 2013 at 09:03:11 UTC, Kagamin wrote:On Thursday, 28 March 2013 at 16:34:47 UTC, Maxim Fomin wrote:You saw one particular example, the problem is much bigger.probably bypassing type system.try to bypass the type system; we just saw the variables are typechecked.
Mar 29 2013
On Friday, 29 March 2013 at 10:37:42 UTC, Maxim Fomin wrote:You saw one particular example, the problem is much bigger.What's problem? Try it.
Apr 01 2013
On Monday, 1 April 2013 at 20:37:34 UTC, Kagamin wrote:On Friday, 29 March 2013 at 10:37:42 UTC, Maxim Fomin wrote:??? What to try? It seems there is misunderstanding. I point out that dmd generates names for pretty much internal staff and does not protect them, so they can be manipulated which is accepts-invalid. Such manipulation can probably lead to bypassing type system constraints. The fact that one particular example does not allow to do so, does not necessarily means that no one can. "Program testing can be used to show the presence of bugs, but never to show their absence!" Dijkstra.You saw one particular example, the problem is much bigger.What's problem? Try it.
Apr 01 2013
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: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(); }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'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
Apr 02 2013
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(); }Then I should probably report this as an issue. -- /Jacob CarlborgI'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
Apr 02 2013
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
Apr 02 2013