GNOME Bugzilla – Bug 599133
GList foreach iterator variable not captured by closure
Last modified: 2018-04-25 09:29:06 UTC
When trying to create a closure that uses the variable used as the iterator in a foreach block, Vala fails to capture said variable, leading to lots of confusion. For example: foreach(SomeType a in my_list) { Gtk.Button button = new Gtk.Button(); button.clicked.connect(() -> { // a is null }); } Expected results: a is captured, just like 'button', and variables from higher up in the scope. Actual results: a is null, and a quick readthrough of the generated C shows that it's never assigned to anything (within the "Block1Data" struct). Caveats: I've tried this both on the current Git tree and 0.7.7. It's broken on both. Workaround: I'm currently just creating another variable referring to the same thing: foreach(SomeType a in my_list) { Gtk.Button button = new Gtk.Button(); var real_a = a; button.clicked.connect(() -> { // a is null // real_a is what it should be!! }); } This works, but it is certainly not attractive.
Created attachment 145913 [details] Test case
Confirming, only affects collectoins without native iterator support such as GList.
Hi, this bug also occours on string[] with vala 0.11.2. I'm also appending my test case, thanks to the IRC people for helping me track it down :) It's slightly different, and if you run it you get an assertation failed warning.
Created attachment 174613 [details] my test case on using a string[]
Created attachment 174614 [details] The C code generated for the test case Error is betwen line 110 and 113, it never assigns _data1_->select_button_tex
The following test case prints the items that are enclosed from the GList correctly: void main () { List<string> list = new List<string> (); list.append ("one"); list.append ("two"); list.append ("three"); var test = new Test (); foreach (var item in list) { test.show.connect (() => { print (item + "\n"); }); } test.show (); } class Test { public signal void show (); } The output is: one two three as expected.