]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Support chain up to simple generics constructor
authorSimon Werbeck <simon.werbeck@gmail.com>
Tue, 24 Mar 2020 15:47:18 +0000 (16:47 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 30 Dec 2020 14:06:31 +0000 (15:06 +0100)
This allows subclassing bindings like GLib.HashTable and GLib.Sequence
that require implicit DestroyNotify parameters to chain up.

Fixes https://gitlab.gnome.org/GNOME/vala/issues/342

codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
tests/Makefile.am
tests/objects/simple-generics-chainup.vala [new file with mode: 0644]

index 393bb16ff92b25d2c0de1913a0241bab0d9e2fe1..b1f7e68699f447e0e8d08a6cd6e25be6d0bba45b 100644 (file)
@@ -4744,9 +4744,19 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
        public virtual void generate_error_domain_declaration (ErrorDomain edomain, CCodeFile decl_space) {
        }
 
-       public void add_generic_type_arguments (Map<int,CCodeExpression> arg_map, List<DataType> type_args, CodeNode expr, bool is_chainup = false, List<TypeParameter>? type_parameters = null) {
+       public void add_generic_type_arguments (Method m, Map<int,CCodeExpression> arg_map, List<DataType> type_args, CodeNode expr, bool is_chainup = false, List<TypeParameter>? type_parameters = null) {
                int type_param_index = 0;
                foreach (var type_arg in type_args) {
+                       if (get_ccode_simple_generics (m)) {
+                               if (requires_copy (type_arg)) {
+                                       arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), get_destroy0_func_expression (type_arg, is_chainup));
+                               } else {
+                                       arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), new CCodeConstant ("NULL"));
+                               }
+                               type_param_index++;
+                               continue;
+                       }
+
                        if (type_parameters != null) {
                                var type_param_name = type_parameters.get (type_param_index).name.ascii_down ().replace ("_", "-");
                                arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeConstant ("\"%s-type\"".printf (type_param_name)));
@@ -4898,18 +4908,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_"));
                        }
 
-                       if (cl != null && !cl.is_compact) {
-                               add_generic_type_arguments (in_arg_map, expr.type_reference.get_type_arguments (), expr);
-                       } else if (cl != null && get_ccode_simple_generics (m)) {
-                               int type_param_index = 0;
-                               foreach (var type_arg in expr.type_reference.get_type_arguments ()) {
-                                       if (requires_copy (type_arg)) {
-                                               in_arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), get_destroy0_func_expression (type_arg));
-                                       } else {
-                                               in_arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), new CCodeConstant ("NULL"));
-                                       }
-                                       type_param_index++;
-                               }
+                       if (cl != null && (!cl.is_compact || get_ccode_simple_generics (m))) {
+                               add_generic_type_arguments (m, in_arg_map, expr.type_reference.get_type_arguments (), expr);
                        }
 
                        bool ellipsis = false;
index bf99ee0116ed5e0a11c81930efe5952bdb8dd943..74e22fb64e71836f8a2490a0ac5df9066507a1c6 100644 (file)
@@ -151,7 +151,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                                // gobject-style chainup
                                                                type_parameters = ((Class) base_type.type_symbol).get_type_parameters ();
                                                        }
-                                                       add_generic_type_arguments (in_arg_map, base_type.get_type_arguments (), expr, true, type_parameters);
+                                                       add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr, true, type_parameters);
                                                        break;
                                                }
                                        }
@@ -181,13 +181,24 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
                                csizeof.add_argument (new CCodeIdentifier (get_ccode_name (current_class)));
                                ccall.add_argument (csizeof);
+                       } else if (current_class.base_class != null && get_ccode_simple_generics (m)) {
+                               if (current_class != m.parent_symbol) {
+                                       foreach (DataType base_type in current_class.get_base_types ()) {
+                                               if (base_type.type_symbol is Class) {
+                                                       add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr);
+                                                       break;
+                                               }
+                                       }
+                               } else {
+                                       // TODO: simple generics are only supported in bindings.
+                               }
                        }
                } else if (m is CreationMethod && m.parent_symbol is Struct) {
                        ccall.add_argument (get_this_cexpression ());
                } else if (m != null && m.has_type_parameters () && !get_ccode_has_generic_type_parameter (m) && !get_ccode_simple_generics (m) && (ccall != finish_call || expr.is_yield_expression)) {
                        // generic method
                        // don't add generic arguments for .end() calls
-                       add_generic_type_arguments (in_arg_map, ma.get_type_arguments (), expr);
+                       add_generic_type_arguments (m, in_arg_map, ma.get_type_arguments (), expr);
                }
 
                // the complete call expression, might include casts, comma expressions, and/or assignments
index 67ec8aeb756a1fd2bfcd4347a1896550d04c0e6f..517d5746a4e084968d61d0c0f09e3e4893d97aa2 100644 (file)
@@ -482,6 +482,7 @@ TESTS = \
        objects/signals-prototype-access-invalid.test \
        objects/signals-prototype-access-invalid-2.test \
        objects/signals-struct-return.vala \
+       objects/simple-generics-chainup.vala \
        objects/singleton.vala \
        objects/type-narrowing.vala \
        objects/type-narrowing-fallback.vala \
diff --git a/tests/objects/simple-generics-chainup.vala b/tests/objects/simple-generics-chainup.vala
new file mode 100644 (file)
index 0000000..6cfd023
--- /dev/null
@@ -0,0 +1,29 @@
+class IntSequence : Sequence<int> {
+}
+
+class StringSequence : Sequence<string> {
+}
+
+class StringIntMap : HashTable<string,int> {
+       public StringIntMap () {
+               base (str_hash, str_equal);
+       }
+}
+
+void main () {
+       {
+               var seq = new IntSequence ();
+               seq.append (23);
+               assert (seq.get_begin_iter ().get () == 23);
+       }
+       {
+               var seq = new StringSequence ();
+               seq.append ("foo");
+               assert (seq.get_begin_iter ().get () == "foo");
+       }
+       {
+               var map = new StringIntMap ();
+               map["foo"] = 42;
+               assert (map["foo"] == 42);
+       }
+}