GNOME Bugzilla – Bug 791060
can't compile generic function where type parameter is passed on in return value
Last modified: 2017-12-06 23:07:16 UTC
This code doesn't compile: ------------------------------ public GenericArray<G> create_generic_array<G> () { GenericArray<G> array = new GenericArray<G>(); return array; } void main () { create_generic_array<int>(); } ------------------------------ /tmp/test.vala.NN7LAZ.c: In function ‘_g_destroy_func0_’: /tmp/test.vala.NN7LAZ.c:18:21: error: ‘g_destroy_func’ undeclared (first use in this function); did you mean ‘_g_destroy_func0_’? ((var == NULL) || (g_destroy_func == NULL)) ? NULL : (var = (g_destroy_func (var), NULL)); ^~~~~~~~~~~~~~ _g_destroy_func0_ /tmp/test.vala.NN7LAZ.c:18:21: note: each undeclared identifier is reported only once for each function it appears in /tmp/test.vala.NN7LAZ.c:18:63: warning: implicit declaration of function ‘g_destroy_func’; did you mean ‘_g_destroy_func0_’? [-Wimplicit-function-declaration] ((var == NULL) || (g_destroy_func == NULL)) ? NULL : (var = (g_destroy_func (var), NULL)); ^~~~~~~~~~~~~~ _g_destroy_func0_
Generics require to know value's type in order to create C code for type creation and destruction, so I think this code should be declared as invalid by the compiler.
(In reply to Daniel Espinosa from comment #1) > Generics require to know value's type in order to create C code for type > creation and destruction The type is specified. See the line in main (): create_generic_array<int>(); So in this example it is an int. Now the destroy function is passed to create_generic_array, which is fine, although it is null in this case when using int. What is happening is the return value of create_generic_array () is also containing a reference to the type parameter. Vala could just pass the destroy function straight through. So if you compile to the C code from Vala and amend it so the line: _tmp0_ = g_ptr_array_new_full ((guint) 0, _g_destroy_func0_); is changed to: _tmp0_ = g_ptr_array_new_full ((guint) 0, g_destroy_func); The C code will now compile and run for the example. The hard part here is getting the Vala compiler to recognise the destroy function has been passed as an argument in a function call and modify the generated C code accordingly. At present g_destroy_func is a local variable in this example. Also note g_ptr_array_new_full () only requires the size and free function, but no type information. I've not tested how Vala behaves when type information is also needed where a generic parameter is passed through to a return value.
(In reply to Al Thomas from comment #2) > (In reply to Daniel Espinosa from comment #1) > > Generics require to know value's type in order to create C code for type > > creation and destruction > > The type is specified. See the line in main (): > create_generic_array<int>(); > You are right, how I don't see it before. > > The hard part here is getting the Vala compiler to recognise the destroy > function has been passed as an argument in a function call and modify the > generated C code accordingly. At present g_destroy_func is a local variable > in this example. > Why Vala is not using GLib.Value for its generics? So it will always know creation, destruction and more. > Also note g_ptr_array_new_full () only requires the size and free function, > but no type information. I've not tested how Vala behaves when type > information is also needed where a generic parameter is passed through to a > return value. May using GLib.Value can improve this situation. I would like to describe my thoughts in more detail on how use it in Vala internals for generics.
Note this situation here is a bit more complicated since it is mixing "normal generics" with "simple generics" and all this in a static context (not wrapped in a class structure).
*** This bug has been marked as a duplicate of bug 791283 ***