After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 599133 - GList foreach iterator variable not captured by closure
GList foreach iterator variable not captured by closure
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Methods
unspecified
Other All
: Normal normal
: ---
Assigned To: Vala maintainers
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2009-10-21 01:59 UTC by Tim Horton
Modified: 2018-04-25 09:29 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case (1.43 KB, text/plain)
2009-10-21 02:13 UTC, Tim Horton
Details
my test case on using a string[] (452 bytes, application/octet-stream)
2010-11-16 17:06 UTC, Steffen Schaumburg
Details
The C code generated for the test case (4.40 KB, text/x-c)
2010-11-16 17:08 UTC, Steffen Schaumburg
Details

Description Tim Horton 2009-10-21 01:59:59 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.
Comment 1 Tim Horton 2009-10-21 02:13:40 UTC
Created attachment 145913 [details]
Test case
Comment 2 Jürg Billeter 2009-10-22 19:42:16 UTC
Confirming, only affects collectoins without native iterator support such as GList.
Comment 3 Steffen Schaumburg 2010-11-16 17:05:58 UTC
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.
Comment 4 Steffen Schaumburg 2010-11-16 17:06:36 UTC
Created attachment 174613 [details]
my test case on using a string[]
Comment 5 Steffen Schaumburg 2010-11-16 17:08:26 UTC
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
Comment 6 Al Thomas 2018-04-25 09:29:06 UTC
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.