]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add no_generics_args attribute
authorLorenz Wildberg <lorenz@wild-fisch.de>
Sat, 24 Jun 2023 15:07:26 +0000 (17:07 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 31 Jan 2024 17:49:07 +0000 (18:49 +0100)
The no_generics_args attribute can be added to anything that can have
generics, for example classes, interfaces and methods. It makes the C
code generation not emit parameters, properties fields, etc. for the
storage or passing over of type parameters. This means 3 things: the
type id, copy function and free function.

The attribute works in .vapi files as well as full implementations in
.vala files.

But these values still need to be taken from somewhere to for example
copy an object with the type of the type parameter. For this reason it
is required that there is a constrain for the generic parameter. The
constrain needs to be an "object" type. So a type derived from
GTypeInstance. This can be standard vala classes with or without
GLib.Object as a base or Interfaces. It is because these types provide
ref- and unref-functions. These together with the type id are used as
constants instead of the variable type passed through parameters.

The attribute applied on a type makes all its type parameters
not emit no generic arguments.

20 files changed:
codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagobjectmodule.vala
codegen/valagtypemodule.vala
tests/Makefile.am
tests/bindings/gio/listmodel-compatibility.c-expected [new file with mode: 0644]
tests/bindings/gio/listmodel-compatibility.vala [new file with mode: 0644]
tests/generics/no-generic-args-use-with-proper-generic-type-2.test [new file with mode: 0644]
tests/generics/no-generic-args-use-with-proper-generic-type.test [new file with mode: 0644]
tests/generics/no-generic-args-with-no-constraint.test [new file with mode: 0644]
tests/generics/no-generic-args.vala [new file with mode: 0644]
tests/generics/typeof-with-no-generic-args.test [new file with mode: 0644]
vala/valadatatype.vala
vala/valagirparser.vala
vala/valamemberaccess.vala
vala/valamethodcall.vala
vala/valatypeofexpression.vala
vala/valatypeparameter.vala
vala/valausedattr.vala

index 8cc088aaf5a87ebfc7c10c21f2ddb1b2c0f8ad9c..ffdfbd143bebb41b60a8069d81270fab025b4e9c 100644 (file)
@@ -3879,9 +3879,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                return new CCodeConstant ("NULL");
                        }
 
-                       // unref functions are optional for type parameters
-                       var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
-                       cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
+                       if (!((GenericType) type).type_parameter.no_generic_args) {
+                               // unref functions are optional for type parameters
+                               var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
+                               cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
+                       }
                }
 
                // glib collections already have the free_func argument, so make sure the instance parameter gets first
@@ -4821,7 +4823,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                ccallarg = cexpr;
                        }
                        var cnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cexpr, new CCodeConstant ("NULL"));
-                       if (type is GenericType) {
+                       if (type is GenericType && !((GenericType) type).type_parameter.no_generic_args) {
                                // dup functions are optional for type parameters
                                var cdupnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_dup_func_expression (type, node.source_reference), new CCodeConstant ("NULL"));
                                cnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.AND, cnotnull, cdupnotnull);
@@ -5077,7 +5079,7 @@ 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 || get_ccode_simple_generics (m))) {
+                       if (cl != null && !cl.get_attribute_bool ("CCode", "no_generic_args", false) && (!cl.is_compact || get_ccode_simple_generics (m))) {
                                add_generic_type_arguments (m, in_arg_map, expr.type_reference.get_type_arguments (), expr);
                        }
 
index 95087b535a2a62adc23dfd167333c46bd27e57b5..1277799b12abc1c71a1a3b0fdd1c187974256801 100644 (file)
@@ -165,6 +165,9 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        // chain up to base class
                                        foreach (DataType base_type in current_class.get_base_types ()) {
                                                if (base_type.type_symbol is Class) {
+                                                       if (((Class) base_type.type_symbol).get_attribute_bool ("CCode", "no_generic_args", false)) {
+                                                               break;
+                                                       }
                                                        List<TypeParameter> type_parameters = null;
                                                        if (get_ccode_real_name (m) == "g_object_new") {
                                                                // gobject-style chainup
@@ -179,6 +182,9 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        // chain up to other constructor in same class
                                        var cl = (Class) m.parent_symbol;
                                        foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+                                               if (type_param.no_generic_args) {
+                                                       continue;
+                                               }
                                                in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier (get_ccode_type_id (type_param)));
                                                in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_copy_function (type_param)));
                                                in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier (get_ccode_destroy_function (type_param)));
@@ -188,6 +194,9 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                if (current_class.has_type_parameters () && get_ccode_real_name (m) == "g_object_new") {
                                        // gobject-style construction
                                        foreach (var type_param in current_class.get_type_parameters ()) {
+                                               if (type_param.no_generic_args) {
+                                                       continue;
+                                               }
                                                var type_param_name = type_param.name.ascii_down ().replace ("_", "-");
                                                in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeConstant ("\"%s-type\"".printf (type_param_name)));
                                                in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_type_id (type_param)));
@@ -380,6 +389,9 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                /* type, dup func, and destroy func fields for generic types */
                                var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv");
                                foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
+                                       if (type_param.no_generic_args) {
+                                               continue;
+                                       }
                                        var type = get_ccode_type_id (type_param);
                                        var dup_func = get_ccode_copy_function (type_param);
                                        var destroy_func = get_ccode_destroy_function (type_param);
index 05b9a29166da1d5e271fa9b4db98adf67aa494cf..d5e68609e765df4a1ddb67f1de2e60bdcc38cc67 100644 (file)
@@ -535,6 +535,9 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                        // allow capturing generic type parameters
                                        var data_var = get_variable_cexpression ("_data%d_".printf (block_id));
                                        foreach (var type_param in m.get_type_parameters ()) {
+                                               if (type_param.no_generic_args) {
+                                                       continue;
+                                               }
                                                var type = get_ccode_type_id (type_param);
                                                var dup_func = get_ccode_copy_function (type_param);
                                                var destroy_func = get_ccode_destroy_function (type_param);
@@ -635,6 +638,9 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                                        /* type, dup func, and destroy func fields for generic types */
                                                        var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv");
                                                        foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
+                                                               if (type_param.no_generic_args) {
+                                                                       continue;
+                                                               }
                                                                var type = get_ccode_type_id (type_param);
                                                                var dup_func = get_ccode_copy_function (type_param);
                                                                var destroy_func = get_ccode_destroy_function (type_param);
@@ -1080,6 +1086,9 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                if (type_parameters != null) {
                        int type_param_index = 0;
                        foreach (var type_param in type_parameters) {
+                               if (type_param.no_generic_args) {
+                                       continue;
+                               }
                                cfile.add_include ("glib-object.h");
                                var type = get_ccode_type_id (type_param);
                                var dup_func = get_ccode_copy_function (type_param);
index c380763b880201fbb1ef24bef9fcdd036e0dba98..ed8834299b8f2a637d47657d5135e7b5681c8a67 100644 (file)
@@ -74,6 +74,9 @@ public class Vala.GObjectModule : GTypeModule {
 
                /* create type, dup_func, and destroy_func properties for generic types */
                foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+                       if (type_param.no_generic_args) {
+                               continue;
+                       }
                        string func_name, enum_value;
                        CCodeConstant func_name_constant;
                        CCodeFunctionCall cinst, cspec;
@@ -304,6 +307,9 @@ public class Vala.GObjectModule : GTypeModule {
 
                /* type, dup func, and destroy func properties for generic types */
                foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+                       if (type_param.no_generic_args) {
+                               continue;
+                       }
                        string func_name, enum_value;
                        CCodeMemberAccess cfield;
                        CCodeFunctionCall csetcall;
@@ -439,6 +445,9 @@ public class Vala.GObjectModule : GTypeModule {
 
                /* type, dup func, and destroy func properties for generic types */
                foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+                       if (type_param.no_generic_args) {
+                               continue;
+                       }
                        string func_name, enum_value;
                        CCodeMemberAccess cfield;
                        CCodeFunctionCall cgetcall;
index ec103d2f4f048092f6cc47ebe365674a7adc3297..f238ebded0544f9377c3eba7bb525ef83cf4d977 100644 (file)
@@ -549,6 +549,9 @@ public class Vala.GTypeModule : GErrorModule {
                if (is_gtypeinstance) {
                        /* create type, dup_func, and destroy_func fields for generic types */
                        foreach (TypeParameter type_param in cl.get_type_parameters ()) {
+                               if (type_param.no_generic_args) {
+                                       continue;
+                               }
                                instance_priv_struct.add_field ("GType", get_ccode_type_id (type_param));
                                instance_priv_struct.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param));
                                instance_priv_struct.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param));
index 2e6c1f7f0fb740959835ec8c71441a83b57d4f8a..6dbed7baadd5df3f4ec79bb6385336a26bfaf034 100644 (file)
@@ -842,6 +842,10 @@ TESTS = \
        generics/method-to-delegate-incompatible-2.test \
        generics/method-to-delegate-incompatible-3.test \
        generics/multiple-classes-constraints.test \
+       generics/no-generic-args.vala \
+       generics/no-generic-args-use-with-proper-generic-type.test \
+       generics/no-generic-args-use-with-proper-generic-type-2.test \
+       generics/no-generic-args-with-no-constraint.test \
        generics/null-type.vala \
        generics/property-gobject-set.vala \
        generics/property-int-cast.vala \
@@ -851,6 +855,7 @@ TESTS = \
        generics/type-parameter-properties.vala \
        generics/type-parameter-property-clash.vala \
        generics/type-parameter-static-in-runtime.test \
+       generics/typeof-with-no-generic-args.test \
        generics/value-pointer-type-access.vala \
        generics/bug640330.vala \
        generics/bug640330-2.test \
@@ -1493,6 +1498,7 @@ TESTS = \
        genie/while.gs \
        glib/conditional-glib-api.vala \
        bindings/gio/memoryoutputstream.vala \
+       bindings/gio/listmodel-compatibility.vala \
        $(LINUX_TESTS) \
        $(NULL)
 
diff --git a/tests/bindings/gio/listmodel-compatibility.c-expected b/tests/bindings/gio/listmodel-compatibility.c-expected
new file mode 100644 (file)
index 0000000..054b893
--- /dev/null
@@ -0,0 +1,637 @@
+/* bindings_gio_listmodel_compatibility.c generated by valac, the Vala compiler
+ * generated from bindings_gio_listmodel_compatibility.vala, do not modify */
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define TYPE_NOT_ALIST_VIEW (not_alist_view_get_type ())
+#define NOT_ALIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOT_ALIST_VIEW, NotAListView))
+#define NOT_ALIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOT_ALIST_VIEW, NotAListViewClass))
+#define IS_NOT_ALIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOT_ALIST_VIEW))
+#define IS_NOT_ALIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOT_ALIST_VIEW))
+#define NOT_ALIST_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOT_ALIST_VIEW, NotAListViewClass))
+
+typedef struct _NotAListView NotAListView;
+typedef struct _NotAListViewClass NotAListViewClass;
+typedef struct _NotAListViewPrivate NotAListViewPrivate;
+enum  {
+       NOT_ALIST_VIEW_0_PROPERTY,
+       NOT_ALIST_VIEW_G_TYPE_PROPERTY,
+       NOT_ALIST_VIEW_MODEL_PROPERTY,
+       NOT_ALIST_VIEW_NUM_PROPERTIES
+};
+static GParamSpec* not_alist_view_properties[NOT_ALIST_VIEW_NUM_PROPERTIES];
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+
+#define TYPE_FOO (foo_get_type ())
+#define FOO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FOO, Foo))
+#define FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FOO, FooClass))
+#define IS_FOO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FOO))
+#define IS_FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FOO))
+#define FOO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FOO, FooClass))
+
+typedef struct _Foo Foo;
+typedef struct _FooClass FooClass;
+typedef struct _FooPrivate FooPrivate;
+enum  {
+       FOO_0_PROPERTY,
+       FOO_MODEL_PROPERTY,
+       FOO_OTHER_THING_PROPERTY,
+       FOO_NUM_PROPERTIES
+};
+static GParamSpec* foo_properties[FOO_NUM_PROPERTIES];
+
+struct _NotAListView {
+       GObject parent_instance;
+       NotAListViewPrivate * priv;
+};
+
+struct _NotAListViewClass {
+       GObjectClass parent_class;
+};
+
+struct _NotAListViewPrivate {
+       GType _g_type;
+       GListModel* _model;
+};
+
+struct _Foo {
+       GObject parent_instance;
+       FooPrivate * priv;
+};
+
+struct _FooClass {
+       GObjectClass parent_class;
+};
+
+struct _FooPrivate {
+       GListModel* _model;
+       NotAListView* _other_thing;
+};
+
+static gint NotAListView_private_offset;
+static gpointer not_alist_view_parent_class = NULL;
+static gint Foo_private_offset;
+static gpointer foo_parent_class = NULL;
+static GListModelInterface * foo_g_list_model_parent_iface = NULL;
+
+VALA_EXTERN GType not_alist_view_get_type (void) G_GNUC_CONST ;
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (NotAListView, g_object_unref)
+VALA_EXTERN NotAListView* not_alist_view_new_with_type (GType g_type);
+VALA_EXTERN NotAListView* not_alist_view_construct_with_type (GType object_type,
+                                                  GType g_type);
+VALA_EXTERN NotAListView* not_alist_view_new (void);
+VALA_EXTERN NotAListView* not_alist_view_construct (GType object_type);
+VALA_EXTERN GType not_alist_view_get_g_type (NotAListView* self);
+static void not_alist_view_set_g_type (NotAListView* self,
+                                GType value);
+VALA_EXTERN GListModel* not_alist_view_get_model (NotAListView* self);
+VALA_EXTERN void not_alist_view_set_model (NotAListView* self,
+                               GListModel* value);
+static GObject * not_alist_view_constructor (GType type,
+                                      guint n_construct_properties,
+                                      GObjectConstructParam * construct_properties);
+static void not_alist_view_finalize (GObject * obj);
+static GType not_alist_view_get_type_once (void);
+static void _vala_not_alist_view_get_property (GObject * object,
+                                        guint property_id,
+                                        GValue * value,
+                                        GParamSpec * pspec);
+static void _vala_not_alist_view_set_property (GObject * object,
+                                        guint property_id,
+                                        const GValue * value,
+                                        GParamSpec * pspec);
+VALA_EXTERN GType foo_get_type (void) G_GNUC_CONST ;
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Foo, g_object_unref)
+static GType foo_real_get_item_type (GListModel* base);
+static GObject* foo_real_get_item (GListModel* base,
+                            guint pos);
+static guint foo_real_get_n_items (GListModel* base);
+VALA_EXTERN Foo* foo_new (void);
+VALA_EXTERN Foo* foo_construct (GType object_type);
+VALA_EXTERN GListModel* foo_get_model (Foo* self);
+VALA_EXTERN void foo_set_model (Foo* self,
+                    GListModel* value);
+VALA_EXTERN NotAListView* foo_get_other_thing (Foo* self);
+VALA_EXTERN void foo_set_other_thing (Foo* self,
+                          NotAListView* value);
+static void foo_finalize (GObject * obj);
+static GType foo_get_type_once (void);
+static void _vala_foo_get_property (GObject * object,
+                             guint property_id,
+                             GValue * value,
+                             GParamSpec * pspec);
+static void _vala_foo_set_property (GObject * object,
+                             guint property_id,
+                             const GValue * value,
+                             GParamSpec * pspec);
+static void _vala_main (void);
+
+static inline gpointer
+not_alist_view_get_instance_private (NotAListView* self)
+{
+       return G_STRUCT_MEMBER_P (self, NotAListView_private_offset);
+}
+
+NotAListView*
+not_alist_view_construct_with_type (GType object_type,
+                                    GType g_type)
+{
+       NotAListView * self = NULL;
+       self = (NotAListView*) g_object_new (object_type, "g-type", g_type, NULL);
+       return self;
+}
+
+NotAListView*
+not_alist_view_new_with_type (GType g_type)
+{
+       return not_alist_view_construct_with_type (TYPE_NOT_ALIST_VIEW, g_type);
+}
+
+NotAListView*
+not_alist_view_construct (GType object_type)
+{
+       NotAListView * self = NULL;
+       self = (NotAListView*) g_object_new (object_type, NULL);
+       return self;
+}
+
+NotAListView*
+not_alist_view_new (void)
+{
+       return not_alist_view_construct (TYPE_NOT_ALIST_VIEW);
+}
+
+GType
+not_alist_view_get_g_type (NotAListView* self)
+{
+       GType result;
+       g_return_val_if_fail (IS_NOT_ALIST_VIEW (self), 0UL);
+       result = self->priv->_g_type;
+       return result;
+}
+
+static void
+not_alist_view_set_g_type (NotAListView* self,
+                           GType value)
+{
+       GType old_value;
+       g_return_if_fail (IS_NOT_ALIST_VIEW (self));
+       old_value = not_alist_view_get_g_type (self);
+       if (old_value != value) {
+               self->priv->_g_type = value;
+               g_object_notify_by_pspec ((GObject *) self, not_alist_view_properties[NOT_ALIST_VIEW_G_TYPE_PROPERTY]);
+       }
+}
+
+GListModel*
+not_alist_view_get_model (NotAListView* self)
+{
+       GListModel* result;
+       GListModel* _tmp0_;
+       g_return_val_if_fail (IS_NOT_ALIST_VIEW (self), NULL);
+       _tmp0_ = self->priv->_model;
+       result = _tmp0_;
+       return result;
+}
+
+static gpointer
+_g_object_ref0 (gpointer self)
+{
+       return self ? g_object_ref (self) : NULL;
+}
+
+void
+not_alist_view_set_model (NotAListView* self,
+                          GListModel* value)
+{
+       GListModel* old_value;
+       g_return_if_fail (IS_NOT_ALIST_VIEW (self));
+       old_value = not_alist_view_get_model (self);
+       if (old_value != value) {
+               GListModel* _tmp0_;
+               _tmp0_ = _g_object_ref0 (value);
+               _g_object_unref0 (self->priv->_model);
+               self->priv->_model = _tmp0_;
+               g_object_notify_by_pspec ((GObject *) self, not_alist_view_properties[NOT_ALIST_VIEW_MODEL_PROPERTY]);
+       }
+}
+
+static GObject *
+not_alist_view_constructor (GType type,
+                            guint n_construct_properties,
+                            GObjectConstructParam * construct_properties)
+{
+       GObject * obj;
+       GObjectClass * parent_class;
+       NotAListView * self;
+       GType _tmp0_;
+       GListStore* _tmp1_;
+       GListStore* _tmp2_;
+       parent_class = G_OBJECT_CLASS (not_alist_view_parent_class);
+       obj = parent_class->constructor (type, n_construct_properties, construct_properties);
+       self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_NOT_ALIST_VIEW, NotAListView);
+       _tmp0_ = self->priv->_g_type;
+       _tmp1_ = g_list_store_new (_tmp0_);
+       _tmp2_ = _tmp1_;
+       not_alist_view_set_model (self, G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, g_list_model_get_type (), GListModel));
+       _g_object_unref0 (_tmp2_);
+       return obj;
+}
+
+static void
+not_alist_view_class_init (NotAListViewClass * klass,
+                           gpointer klass_data)
+{
+       not_alist_view_parent_class = g_type_class_peek_parent (klass);
+       g_type_class_adjust_private_offset (klass, &NotAListView_private_offset);
+       G_OBJECT_CLASS (klass)->get_property = _vala_not_alist_view_get_property;
+       G_OBJECT_CLASS (klass)->set_property = _vala_not_alist_view_set_property;
+       G_OBJECT_CLASS (klass)->constructor = not_alist_view_constructor;
+       G_OBJECT_CLASS (klass)->finalize = not_alist_view_finalize;
+       g_object_class_install_property (G_OBJECT_CLASS (klass), NOT_ALIST_VIEW_G_TYPE_PROPERTY, not_alist_view_properties[NOT_ALIST_VIEW_G_TYPE_PROPERTY] = g_param_spec_gtype ("g-type", "g-type", "g-type", G_TYPE_OBJECT, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (G_OBJECT_CLASS (klass), NOT_ALIST_VIEW_MODEL_PROPERTY, not_alist_view_properties[NOT_ALIST_VIEW_MODEL_PROPERTY] = g_param_spec_object ("model", "model", "model", g_list_model_get_type (), G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+static void
+not_alist_view_instance_init (NotAListView * self,
+                              gpointer klass)
+{
+       self->priv = not_alist_view_get_instance_private (self);
+       self->priv->_g_type = G_TYPE_OBJECT;
+}
+
+static void
+not_alist_view_finalize (GObject * obj)
+{
+       NotAListView * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_NOT_ALIST_VIEW, NotAListView);
+       _g_object_unref0 (self->priv->_model);
+       G_OBJECT_CLASS (not_alist_view_parent_class)->finalize (obj);
+}
+
+static GType
+not_alist_view_get_type_once (void)
+{
+       static const GTypeInfo g_define_type_info = { sizeof (NotAListViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) not_alist_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotAListView), 0, (GInstanceInitFunc) not_alist_view_instance_init, NULL };
+       GType not_alist_view_type_id;
+       not_alist_view_type_id = g_type_register_static (G_TYPE_OBJECT, "NotAListView", &g_define_type_info, 0);
+       NotAListView_private_offset = g_type_add_instance_private (not_alist_view_type_id, sizeof (NotAListViewPrivate));
+       return not_alist_view_type_id;
+}
+
+GType
+not_alist_view_get_type (void)
+{
+       static volatile gsize not_alist_view_type_id__once = 0;
+       if (g_once_init_enter (&not_alist_view_type_id__once)) {
+               GType not_alist_view_type_id;
+               not_alist_view_type_id = not_alist_view_get_type_once ();
+               g_once_init_leave (&not_alist_view_type_id__once, not_alist_view_type_id);
+       }
+       return not_alist_view_type_id__once;
+}
+
+static void
+_vala_not_alist_view_get_property (GObject * object,
+                                   guint property_id,
+                                   GValue * value,
+                                   GParamSpec * pspec)
+{
+       NotAListView * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_NOT_ALIST_VIEW, NotAListView);
+       switch (property_id) {
+               case NOT_ALIST_VIEW_G_TYPE_PROPERTY:
+               g_value_set_gtype (value, not_alist_view_get_g_type (self));
+               break;
+               case NOT_ALIST_VIEW_MODEL_PROPERTY:
+               g_value_set_object (value, not_alist_view_get_model (self));
+               break;
+               default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
+static void
+_vala_not_alist_view_set_property (GObject * object,
+                                   guint property_id,
+                                   const GValue * value,
+                                   GParamSpec * pspec)
+{
+       NotAListView * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_NOT_ALIST_VIEW, NotAListView);
+       switch (property_id) {
+               case NOT_ALIST_VIEW_G_TYPE_PROPERTY:
+               not_alist_view_set_g_type (self, g_value_get_gtype (value));
+               break;
+               case NOT_ALIST_VIEW_MODEL_PROPERTY:
+               not_alist_view_set_model (self, g_value_get_object (value));
+               break;
+               default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
+static inline gpointer
+foo_get_instance_private (Foo* self)
+{
+       return G_STRUCT_MEMBER_P (self, Foo_private_offset);
+}
+
+static GType
+foo_real_get_item_type (GListModel* base)
+{
+       Foo * self;
+       GType result;
+       self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_FOO, Foo);
+       result = G_TYPE_OBJECT;
+       return result;
+}
+
+static GObject*
+foo_real_get_item (GListModel* base,
+                   guint pos)
+{
+       Foo * self;
+       GObject* result;
+       self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_FOO, Foo);
+       result = NULL;
+       return result;
+}
+
+static guint
+foo_real_get_n_items (GListModel* base)
+{
+       Foo * self;
+       guint result;
+       self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_FOO, Foo);
+       result = (guint) 0;
+       return result;
+}
+
+Foo*
+foo_construct (GType object_type)
+{
+       Foo * self = NULL;
+       self = (Foo*) g_object_new (object_type, NULL);
+       return self;
+}
+
+Foo*
+foo_new (void)
+{
+       return foo_construct (TYPE_FOO);
+}
+
+GListModel*
+foo_get_model (Foo* self)
+{
+       GListModel* result;
+       GListModel* _tmp0_;
+       g_return_val_if_fail (IS_FOO (self), NULL);
+       _tmp0_ = self->priv->_model;
+       result = _tmp0_;
+       return result;
+}
+
+void
+foo_set_model (Foo* self,
+               GListModel* value)
+{
+       GListModel* old_value;
+       g_return_if_fail (IS_FOO (self));
+       old_value = foo_get_model (self);
+       if (old_value != value) {
+               GListModel* _tmp0_;
+               _tmp0_ = _g_object_ref0 (value);
+               _g_object_unref0 (self->priv->_model);
+               self->priv->_model = _tmp0_;
+               g_object_notify_by_pspec ((GObject *) self, foo_properties[FOO_MODEL_PROPERTY]);
+       }
+}
+
+NotAListView*
+foo_get_other_thing (Foo* self)
+{
+       NotAListView* result;
+       NotAListView* _tmp0_;
+       g_return_val_if_fail (IS_FOO (self), NULL);
+       _tmp0_ = self->priv->_other_thing;
+       result = _tmp0_;
+       return result;
+}
+
+void
+foo_set_other_thing (Foo* self,
+                     NotAListView* value)
+{
+       NotAListView* old_value;
+       g_return_if_fail (IS_FOO (self));
+       old_value = foo_get_other_thing (self);
+       if (old_value != value) {
+               NotAListView* _tmp0_;
+               _tmp0_ = _g_object_ref0 (value);
+               _g_object_unref0 (self->priv->_other_thing);
+               self->priv->_other_thing = _tmp0_;
+               g_object_notify_by_pspec ((GObject *) self, foo_properties[FOO_OTHER_THING_PROPERTY]);
+       }
+}
+
+static void
+foo_class_init (FooClass * klass,
+                gpointer klass_data)
+{
+       foo_parent_class = g_type_class_peek_parent (klass);
+       g_type_class_adjust_private_offset (klass, &Foo_private_offset);
+       G_OBJECT_CLASS (klass)->get_property = _vala_foo_get_property;
+       G_OBJECT_CLASS (klass)->set_property = _vala_foo_set_property;
+       G_OBJECT_CLASS (klass)->finalize = foo_finalize;
+       g_object_class_install_property (G_OBJECT_CLASS (klass), FOO_MODEL_PROPERTY, foo_properties[FOO_MODEL_PROPERTY] = g_param_spec_object ("model", "model", "model", g_list_model_get_type (), G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
+       g_object_class_install_property (G_OBJECT_CLASS (klass), FOO_OTHER_THING_PROPERTY, foo_properties[FOO_OTHER_THING_PROPERTY] = g_param_spec_object ("other-thing", "other-thing", "other-thing", TYPE_NOT_ALIST_VIEW, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+static void
+foo_g_list_model_interface_init (GListModelInterface * iface,
+                                 gpointer iface_data)
+{
+       foo_g_list_model_parent_iface = g_type_interface_peek_parent (iface);
+       iface->get_item_type = (GType (*) (GListModel*)) foo_real_get_item_type;
+       iface->get_item = (GObject* (*) (GListModel*, guint)) foo_real_get_item;
+       iface->get_n_items = (guint (*) (GListModel*)) foo_real_get_n_items;
+}
+
+static void
+foo_instance_init (Foo * self,
+                   gpointer klass)
+{
+       self->priv = foo_get_instance_private (self);
+}
+
+static void
+foo_finalize (GObject * obj)
+{
+       Foo * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_FOO, Foo);
+       _g_object_unref0 (self->priv->_model);
+       _g_object_unref0 (self->priv->_other_thing);
+       G_OBJECT_CLASS (foo_parent_class)->finalize (obj);
+}
+
+static GType
+foo_get_type_once (void)
+{
+       static const GTypeInfo g_define_type_info = { sizeof (FooClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) foo_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Foo), 0, (GInstanceInitFunc) foo_instance_init, NULL };
+       static const GInterfaceInfo g_list_model_info = { (GInterfaceInitFunc) foo_g_list_model_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
+       GType foo_type_id;
+       foo_type_id = g_type_register_static (G_TYPE_OBJECT, "Foo", &g_define_type_info, 0);
+       g_type_add_interface_static (foo_type_id, g_list_model_get_type (), &g_list_model_info);
+       Foo_private_offset = g_type_add_instance_private (foo_type_id, sizeof (FooPrivate));
+       return foo_type_id;
+}
+
+GType
+foo_get_type (void)
+{
+       static volatile gsize foo_type_id__once = 0;
+       if (g_once_init_enter (&foo_type_id__once)) {
+               GType foo_type_id;
+               foo_type_id = foo_get_type_once ();
+               g_once_init_leave (&foo_type_id__once, foo_type_id);
+       }
+       return foo_type_id__once;
+}
+
+static void
+_vala_foo_get_property (GObject * object,
+                        guint property_id,
+                        GValue * value,
+                        GParamSpec * pspec)
+{
+       Foo * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_FOO, Foo);
+       switch (property_id) {
+               case FOO_MODEL_PROPERTY:
+               g_value_set_object (value, foo_get_model (self));
+               break;
+               case FOO_OTHER_THING_PROPERTY:
+               g_value_set_object (value, foo_get_other_thing (self));
+               break;
+               default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
+static void
+_vala_foo_set_property (GObject * object,
+                        guint property_id,
+                        const GValue * value,
+                        GParamSpec * pspec)
+{
+       Foo * self;
+       self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_FOO, Foo);
+       switch (property_id) {
+               case FOO_MODEL_PROPERTY:
+               foo_set_model (self, g_value_get_object (value));
+               break;
+               case FOO_OTHER_THING_PROPERTY:
+               foo_set_other_thing (self, g_value_get_object (value));
+               break;
+               default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
+static void
+_vala_main (void)
+{
+       GListModel* l = NULL;
+       GListStore* _tmp0_;
+       GObject* o = NULL;
+       GListModel* _tmp1_;
+       GObject* _tmp2_;
+       Foo* foo = NULL;
+       Foo* _tmp3_;
+       GListModel* _tmp4_;
+       GListModel* _tmp5_;
+       GListModel* _tmp6_;
+       GObject* _tmp7_;
+       NotAListView* n = NULL;
+       NotAListView* _tmp8_;
+       NotAListView* _tmp9_;
+       GListModel* _tmp10_;
+       GListModel* _tmp11_;
+       GObject* _tmp12_;
+       GListModel* _tmp13_;
+       NotAListView* _tmp14_;
+       NotAListView* _tmp15_;
+       GListModel* _tmp16_;
+       NotAListView* _tmp17_;
+       GListModel* _tmp18_;
+       GListModel* _tmp19_;
+       GListModel* _tmp20_;
+       _tmp0_ = g_list_store_new (g_list_model_get_type ());
+       l = G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, g_list_model_get_type (), GListModel);
+       _tmp1_ = l;
+       _tmp2_ = g_list_model_get_item (_tmp1_, (guint) 10);
+       o = _tmp2_;
+       _tmp3_ = foo_new ();
+       foo = _tmp3_;
+       _tmp4_ = l;
+       foo_set_model (foo, _tmp4_);
+       _tmp5_ = foo_get_model (foo);
+       _tmp6_ = _tmp5_;
+       _tmp7_ = g_list_model_get_item (_tmp6_, (guint) 0);
+       _g_object_unref0 (o);
+       o = _tmp7_;
+       _tmp8_ = not_alist_view_new ();
+       n = _tmp8_;
+       _tmp9_ = n;
+       _tmp10_ = not_alist_view_get_model (_tmp9_);
+       _tmp11_ = _tmp10_;
+       _tmp12_ = g_list_model_get_item (_tmp11_, (guint) 0);
+       _g_object_unref0 (o);
+       o = _tmp12_;
+       _tmp13_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (foo, g_list_model_get_type (), GListModel));
+       _g_object_unref0 (l);
+       l = _tmp13_;
+       _tmp14_ = not_alist_view_new ();
+       _g_object_unref0 (n);
+       n = _tmp14_;
+       _tmp15_ = n;
+       _tmp16_ = l;
+       not_alist_view_set_model (_tmp15_, _tmp16_);
+       _tmp17_ = n;
+       _tmp18_ = not_alist_view_get_model (_tmp17_);
+       _tmp19_ = _tmp18_;
+       _tmp20_ = _g_object_ref0 (_tmp19_);
+       _g_object_unref0 (l);
+       l = _tmp20_;
+       _g_object_unref0 (n);
+       _g_object_unref0 (foo);
+       _g_object_unref0 (o);
+       _g_object_unref0 (l);
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/bindings/gio/listmodel-compatibility.vala b/tests/bindings/gio/listmodel-compatibility.vala
new file mode 100644 (file)
index 0000000..9f2967b
--- /dev/null
@@ -0,0 +1,49 @@
+[CCode (no_generic_args = true)]
+class NotAListView<G> : Object where G : Object {
+       public Type g_type { get; construct; default = typeof (Object); }
+
+       public ListModel<G> model { get; set; }
+
+       public NotAListView.with_type (Type g_type) {
+               Object (g_type: g_type);
+       }
+
+       construct {
+               model = new ListStore<G> (g_type);
+       }
+}
+
+class Foo : Object, ListModel {
+       public ListModel model { get; set; }
+
+       public NotAListView other_thing { get; set; }
+
+       public Type get_item_type () {
+               return typeof (Object);
+       }
+
+       public Object? get_item (uint pos) {
+               return null;
+       }
+
+       public uint get_n_items () {
+               return 0;
+       }
+}
+
+void main () {
+       ListModel l = (ListModel) new ListStore (typeof (ListModel));
+       Object? o = l.get_item (10);
+
+       Foo foo = new Foo ();
+       foo.model = l;
+       o = foo.model.get_item (0);
+
+       NotAListView n = new NotAListView ();
+       o = n.model.get_item (0);
+       l = foo;
+
+       n = new NotAListView ();
+       n.model = l;
+       l = n.model;
+}
diff --git a/tests/generics/no-generic-args-use-with-proper-generic-type-2.test b/tests/generics/no-generic-args-use-with-proper-generic-type-2.test
new file mode 100644 (file)
index 0000000..c806b51
--- /dev/null
@@ -0,0 +1,14 @@
+Invalid Code
+
+void foo<G> () {
+}
+
+[CCode (no_generic_args = true)]
+class Bar<K> : Object {
+       public Bar () {
+               foo<K> ();
+       }
+}
+
+void main () {
+}
diff --git a/tests/generics/no-generic-args-use-with-proper-generic-type.test b/tests/generics/no-generic-args-use-with-proper-generic-type.test
new file mode 100644 (file)
index 0000000..467cbba
--- /dev/null
@@ -0,0 +1,14 @@
+Invalid Code
+
+class Foo<G> : Object {
+}
+
+[CCode (no_generic_args = true)]
+class Bar<K> : Object {
+       public Bar () {
+               var foo = new Foo<K> ();
+       }
+}
+
+void main () {
+}
diff --git a/tests/generics/no-generic-args-with-no-constraint.test b/tests/generics/no-generic-args-with-no-constraint.test
new file mode 100644 (file)
index 0000000..c33f110
--- /dev/null
@@ -0,0 +1,8 @@
+Invalid Code
+
+[CCode (no_generic_args = true)]
+class Foo<G> : Object {
+}
+
+void main () {
+}
diff --git a/tests/generics/no-generic-args.vala b/tests/generics/no-generic-args.vala
new file mode 100644 (file)
index 0000000..47d1088
--- /dev/null
@@ -0,0 +1,22 @@
+
+[CCode (no_generic_args = true)]
+class Foo<G> : Object where G : Object {
+       public G bar { get; set; }
+
+       public G get_b () {
+               return this.bar;
+       }
+
+       public void set_b (G b) {
+               this.bar = b;
+       }
+}
+
+class Baz : Object {
+}
+
+void main () {
+       var f = new Foo<Baz> ();
+       f.set_b (new Baz());
+       Baz b = f.get_b ();
+}
diff --git a/tests/generics/typeof-with-no-generic-args.test b/tests/generics/typeof-with-no-generic-args.test
new file mode 100644 (file)
index 0000000..e2918af
--- /dev/null
@@ -0,0 +1,11 @@
+Invalid Code
+
+[CCode (no_generic_args = true)]
+class Foo<G> : Object where G : Object {
+       public void bar () {
+               var g = typeof (G);
+       }
+}
+
+void main () {
+}
index 97a7202a1e9a8ac159800b8cec40c9f7a0c0a897..8afedc915804f4f0c027ab3347ebf8315c11f525 100644 (file)
@@ -733,6 +733,13 @@ public abstract class Vala.DataType : CodeNode {
                        }
 
                        it.next ();
+
+                       if (!it.get ().no_generic_args && type is GenericType && !(type_symbol is Delegate) && ((TypeParameter) type.type_symbol).no_generic_args) {
+                               error = true;
+                               Report.error (source_reference, "Cannot retrieve runtime information from type-parameter with `[CCode (no_generic_args = true)]' attribute");
+                               return false;
+                       }
+
                        unowned List<DataType> type_constraints = it.get ().get_type_constraints ();
                        foreach (DataType type_constraint in type_constraints) {
                                if (!type.compatible (type_constraint)) {
index 66bfe8b57048c94b3306b6865887b09bf260884e..7b44705450f931fbdcc186f4005e07f011d442ec 100644 (file)
@@ -1848,6 +1848,8 @@ public class Vala.GirParser : CodeVisitor {
                var type_parameters_length = type_parameters.length;
                GLib.StringBuilder current = new GLib.StringBuilder.sized (type_parameters_length);
 
+               type_symbol.set_attribute_bool ("CCode", "no_generic_args", true);
+
                string? constraint = null;
                for (var c = 0 ; c < type_parameters_length ; c++) {
                        if (type_parameters[c] == ',') {
index 08b5b384e90f6354907dbc5f215ab15239b56a69..98cf10d9c517a7688a74daa0f1e4f2112ffcfd21 100644 (file)
@@ -977,7 +977,7 @@ public class Vala.MemberAccess : Expression {
                        // that subtype might not be generic, so do not report an error in that case
                        unowned ObjectType? object_type = instance_type as ObjectType;
                        if (object_type != null && object_type.object_type_symbol.has_type_parameters ()
-                           && !instance_type.has_type_arguments ()) {
+                           && !instance_type.check_type_arguments (context) && !instance_type.has_type_arguments ()) {
                                error = true;
                                Report.error (inner.source_reference, "missing generic type arguments");
                                return false;
index afa120a9c09fa3684e94f4cf701862c804e81440..0d1e887b0ac796c08c0d7f2c23454e41cf074a27 100644 (file)
@@ -381,8 +381,9 @@ public class Vala.MethodCall : Expression, CallableExpression {
                                }
                        }
 
+                       unowned List<DataType> type_args = ma.get_type_arguments ();
                        int n_type_params = m.get_type_parameters ().size;
-                       int n_type_args = ma.get_type_arguments ().size;
+                       int n_type_args = type_args.size;
                        if (n_type_args > 0 && n_type_args < n_type_params) {
                                error = true;
                                Report.error (ma.source_reference, "too few type arguments for `%s'", m.to_string ());
@@ -392,6 +393,12 @@ public class Vala.MethodCall : Expression, CallableExpression {
                                Report.error (ma.source_reference, "too many type arguments for `%s'", m.to_string ());
                                return false;
                        }
+
+                       if (n_type_args >= 1 && type_args[0] is GenericType && ((TypeParameter) type_args[0].type_symbol).no_generic_args) {
+                               error = true;
+                               Report.error (ma.source_reference, "Cannot retrieve runtime information from type-parameter with `[CCode (no_generic_args = true)]' attribute");
+                               return false;
+                       }
                }
 
                // FIXME partial code duplication in ObjectCreationExpression.check
index 2449b6086fad8db3fe67a51a7a1373f10bc57a0a..e1a0b0de726d8380c62c9f70c292f2544edf5a28 100644 (file)
@@ -90,6 +90,11 @@ public class Vala.TypeofExpression : Expression {
                        Report.warning (_data_type.source_reference, "Arrays do not have a `GLib.Type', with the exception of `string[]'");
                }
 
+               if (type_reference.type_symbol is TypeParameter && ((TypeParameter) type_reference.type_symbol).no_generic_args) {
+                       Report.error (_data_type.source_reference, "You cannot retrieve type parameters of types with the `[CCode (no_generic_args=true)]' attribute");
+                       error = true;
+               }
+
                return !error;
        }
 
index 29db5df39453807268b1d4cb6131565d77c5cbba..95a8c1745e0e9de889f5ce74daf20acd24a91146 100644 (file)
@@ -29,6 +29,12 @@ public class Vala.TypeParameter : TypeSymbol {
        List<DataType> type_constraint_list;
        static List<DataType> _empty_type_list;
 
+       public bool no_generic_args {
+               get {
+                       return parent_symbol.get_attribute_bool ("CCode", "no_generic_args", false);
+               }
+       }
+
        /**
         * Creates a new generic type parameter.
         *
@@ -164,6 +170,12 @@ public class Vala.TypeParameter : TypeSymbol {
                        Report.error (source_reference, "currently it is only supported to constrain a type parameter with one type");
                        error = true;
                }
+
+               if (no_generic_args && !has_type_constraints ()) {
+                       Report.error (source_reference, "type parameters need to be constrained for using `no_generic_args'");
+                       error = true;
+               }
+
                return !error;
        }
 }
index 8823b9122c715d39026f4f6cf52b708292f7605c..a68544c3f559de5e143c53f6bfdd9aa07fee31f9 100644 (file)
@@ -36,7 +36,7 @@ public class Vala.UsedAttr : CodeVisitor {
                "param_spec_function", "has_target", "has_typedef", "type_cname", "ref_function", "ref_function_void", "unref_function", "type",
                "has_construct_function", "returns_floating_reference", "gir_namespace", "gir_version", "construct_function",
                "lower_case_cprefix", "simple_generics", "sentinel", "scope", "has_destroy_function", "ordering", "type_check_function", "type_get_function",
-               "has_copy_function", "lower_case_csuffix", "ref_sink_function", "dup_function", "finish_function", "generic_type_pos",
+               "has_copy_function", "lower_case_csuffix", "ref_sink_function", "dup_function", "finish_function", "generic_type_pos", "no_generic_args",
                "array_length_type", "array_length", "array_length_cname", "array_length_cexpr", "array_null_terminated",
                "vfunc_name", "finish_vfunc_name", "finish_name", "free_function_address_of", "pos", "delegate_target", "delegate_target_cname",
                "array_length_pos", "delegate_target_pos", "destroy_notify_pos", "ctype", "has_new_function", "notify", "finish_instance",