GNOME Bugzilla – Bug 628336
foreach variable isn't copied into block data struct
Last modified: 2012-06-24 19:10:05 UTC
The following Vala code generates some valid C code, but the C code doesn't copy "foo" around properly: the BlockXXData struct for the lambda function will contain a "foo" member, but it won't be set, and thus will always be NULL. foreach (string foo in some_string_array) { do_something_with_string (foo); some_function_which_takes_a_lambda (foo, (l) => { do_something_else_with_string (foo); }); } We experienced this problem at individual.vala:251 (in add_personas()) in libfolks. If you need a working test case, please let me know and I'll come up with one.
It seems to only misbehave with arrays. Gee collections work fine.
Is this still true in 0.10.x and 0.11.x?
Still true in Vala 0.11.2.27-c83f7. The following Vala: foreach (unowned string prop_name in persona.linkable_properties) { unowned ObjectClass pclass = persona.get_class (); if (pclass.find_property (prop_name) == null) { warning ( /* Translators: the parameter is a property name. */ _("Unknown property '%s' in linkable property list."), prop_name); continue; } persona.linkable_property_to_links (prop_name, (l) => { string prop_linking_value = (string) l; Individual candidate_ind = this.link_map.lookup (prop_linking_value); if (candidate_ind != null && candidate_ind.trust_level != TrustLevel.NONE && !candidate_ind_set.contains (candidate_ind)) { debug (" Found candidate individual '%s' by " + "linkable property '%s' = '%s'.", candidate_ind.id, prop_name, prop_linking_value); candidate_inds.add (candidate_ind); candidate_ind_set.add (candidate_ind); } }); } gets compiled to the following C code: gchar** prop_name_collection; int prop_name_collection_length1; int prop_name_it; prop_name_collection = _tmp19_; prop_name_collection_length1 = _tmp20_; for (prop_name_it = 0; prop_name_it < _tmp20_; prop_name_it = prop_name_it + 1) { const gchar* prop_name; prop_name = prop_name_collection[prop_name_it]; { Block14Data* _data14_; GObjectClass* _tmp21_ = NULL; GObjectClass* pclass; GParamSpec* _tmp22_ = NULL; _data14_ = g_slice_new0 (Block14Data); _data14_->_ref_count_ = 1; _data14_->_data13_ = block13_data_ref (_data13_); _tmp21_ = G_OBJECT_GET_CLASS ((GObject*) persona); pclass = _tmp21_; _tmp22_ = g_object_class_find_property (pclass, _data14_->prop_name); if (_tmp22_ == NULL) { const gchar* _tmp23_ = NULL; _tmp23_ = _ ("Unknown property '%s' in linkable property list."); g_warning (_tmp23_, _data14_->prop_name); block14_data_unref (_data14_); continue; } folks_persona_linkable_property_to_links (persona, _data14_->prop_name, __lambda19__folks_persona_linkable_property_callback, _data14_); block14_data_unref (_data14_); } } where Block14Data is defined as: struct _Block14Data { int _ref_count_; Block13Data * _data13_; const gchar* prop_name; }; Note that the C code doesn't fill in Block14Data::prop_name. Changing the Vala to the following fixes the C code: foreach (unowned string foo in persona.linkable_properties) { /* FIXME: If we just use string prop_name directly in the * foreach, Vala doesn't copy it into the closure data, and * prop_name ends up as NULL. bgo#628336 */ unowned string prop_name = foo; unowned ObjectClass pclass = persona.get_class (); …
*** Bug 637714 has been marked as a duplicate of this bug. ***
*** Bug 652446 has been marked as a duplicate of this bug. ***
*** Bug 660927 has been marked as a duplicate of this bug. ***
*** Bug 672767 has been marked as a duplicate of this bug. ***
I can confirm with Vala 0.14.2. Btw the same for "for-loop", but in this case it's more dangerous because vala properly compiles it, but it is referencing wrong objects then. For "foreach" cases valac version 0.14.x reports error and does not compile it.
*** Bug 673902 has been marked as a duplicate of this bug. ***
commit 6cf2c6d828731ae6f56b53ade738732a0d5012a8 Author: Jürg Billeter <j@bitron.ch> Date: Fri May 25 12:25:32 2012 +0200 codegen: Fix capturing element variable of foreach without iterator