From: Simon Werbeck Date: Tue, 24 Mar 2020 15:47:18 +0000 (+0100) Subject: codegen: Support chain up to simple generics constructor X-Git-Tag: 0.51.1~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=189c9093115802bb3b6170f280393076660d0097;p=thirdparty%2Fvala.git codegen: Support chain up to simple generics constructor 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 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 393bb16ff..b1f7e6869 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -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 arg_map, List type_args, CodeNode expr, bool is_chainup = false, List? type_parameters = null) { + public void add_generic_type_arguments (Method m, Map arg_map, List type_args, CodeNode expr, bool is_chainup = false, List? 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; diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index bf99ee011..74e22fb64 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -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 diff --git a/tests/Makefile.am b/tests/Makefile.am index 67ec8aeb7..517d5746a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..6cfd02311 --- /dev/null +++ b/tests/objects/simple-generics-chainup.vala @@ -0,0 +1,29 @@ +class IntSequence : Sequence { +} + +class StringSequence : Sequence { +} + +class StringIntMap : HashTable { + 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); + } +}