GNOME Bugzilla – Bug 725759
Arguments are copied incorrectly when the parameter type is a generic array
Last modified: 2018-02-24 15:35:09 UTC
Consider this fragment: public class Vector<T> { internal T[] items; .... public Vector.from(T[] source) { items = source; } } We can now conveniently initialize the vector like this: new Vector<string>.from({"Fred", "Daphne", "Velma"}) But the problem arises that if we do the same thing with integers: new Vector<int>.from({1, 2, 3}) The c compiler gives the warning: warning: incompatible pointer types passing 'gint *' (aka 'int *') to parameter of type 'gpointer *' (aka 'void **') but the real problem is that the content of 'items' is corrupted. On inspecting the generated C code, there's a line that copies the array to a temporary variable: _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup1 (_tmp0_, _tmp0__length1, t_dup_func) : ((gpointer) _tmp0_); _vala_array_dup1 expects the elements of 'source' to be gpointers but since they may be other smaller primitive types the array copy ends up being corrupt. I think this could be fixed if t_type (from the generic method parameters) was used to copy/pack _tmp0_ into _tmp1_. And then a gpointer* cast when calling the method would remove the compiler warning.
Thanks for your report. Elements with smaller size of a pointer is not a problem. Can you please given a concrete example of corruption?
*Can you please provide a concrete example of corruption?
Created attachment 271061 [details] Examples of types used with generics and array parameters The output I get from executing this code is: Vala Bug 725759 The next line should read 'Fred, Daphne, Velma, Scooby, Shaggy': Fred, Daphne, Velma, Scooby, Shaggy The next line should read '501, 502, 503, 504, 505, 506': 501, 502, 503, 504, 505, 506 The next line should read '601, 602, 603, 604, 605, 606': 601, 603, 605, 0, 0, 0 The next line should read 'a, b, c, d, e, f': a,
Created attachment 271117 [details] Workaround for last bug example Luca, thanks for the information re: typeof. I used it to create this "type aware" array copy to work around the type unaware behavior. It comes at the cost of lots of compiler casting warnings. The result from this code is now correct (although this doesn't fix the bug - it just side steps it): Vala Bug 725759 The next line should read 'Fred, Daphne, Velma, Scooby, Shaggy': Fred, Daphne, Velma, Scooby, Shaggy The next line should read '501, 502, 503, 504, 505, 506': 501, 502, 503, 504, 505, 506 The next line should read '601, 602, 603, 604, 605, 606': 601, 602, 603, 604, 605, 606 The next line should read 'a, b, c, d, e, f': a, b, c, d, e, f
The shorthand in Vala for the workaround is to make the value types maybe types. They are then generated as reference types and so work with Vala's pointer based generics system. This is called "boxing". You still get the C casting warnings at present. The code for your example would be: --- bug725759.vala 2018-02-24 15:22:26.853250046 +0000 +++ bug725759-with-boxing.vala 2018-02-24 15:23:46.894703482 +0000 @@ -27,21 +27,21 @@ a.get(4)); print("The next line should read '501, 502, 503, 504, 505, 506':\n"); - var b = new Vector<long>.from({501l, 502l, 503l, 504l, 505l, 506l}); + var b = new Vector<long?>.from({501l, 502l, 503l, 504l, 505l, 506l}); print("%ld, %ld, %ld, %ld, %ld, %ld\n\n", b.get(0), b.get(1), b.get(2), b.get(3), b.get(4), b.get(5)); print("The next line should read '601, 602, 603, 604, 605, 606':\n"); - var c = new Vector<int>.from({601, 602, 603, 604, 605, 606}); + var c = new Vector<int?>.from({601, 602, 603, 604, 605, 606}); print("%d, %d, %d, %d, %d, %d\n\n", c.get(0), c.get(1), c.get(2), c.get(3), c.get(4), c.get(5)); print("The next line should read 'a, b, c, d, e, f':\n"); - var d = new Vector<char>.from({'a', 'b', 'c', 'd', 'e', 'f'}); + var d = new Vector<char?>.from({'a', 'b', 'c', 'd', 'e', 'f'}); print("%c, %c, %c, %c, %c, %c\n\n", d.get(0), d.get(1), d.get(2), d.get(3),
*** This bug has been marked as a duplicate of bug 774713 ***