CCodeExpression delegate_target_destroy_notify;
get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify);
set_cvalue (expr, delegate_target_destroy_notify);
+ } else if (expr.symbol_reference is GenericDupField) {
+ set_cvalue (expr, get_dup_func_expression (expr.inner.value_type, expr.source_reference));
+ } else if (expr.symbol_reference is GenericDestroyField) {
+ set_cvalue (expr, get_destroy_func_expression (expr.inner.value_type));
} else if (expr.symbol_reference is Field) {
var field = (Field) expr.symbol_reference;
if (expr.lvalue) {
generics/constructor-chain-up.vala \
generics/inference-static-function.vala \
generics/parameter-sizeof-initializer.vala \
+ generics/member-dup-destroy.vala \
generics/type-parameter-properties.vala \
generics/bug640330.test \
generics/bug640330.vala \
--- /dev/null
+delegate void FooFunc ();
+
+class Foo<G> : Object {
+ public Foo () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public void foo () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public async void foo_async () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public void foo_captured () {
+ FooFunc f = () => {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ };
+ f ();
+ }
+}
+
+void bar<T> (T t) {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+}
+
+async void bar_async<T> (T t) {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+}
+
+void bar_captured<T> (T t) {
+ FooFunc f = () => {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+ };
+ f ();
+}
+
+void main () {
+ var foo = new Foo<string> ();
+
+ foo.foo ();
+ foo.foo_async.begin ();
+ foo.foo_captured ();
+
+ bar<Foo> (foo);
+ bar_async<Foo>.begin (foo);
+ bar_captured<Foo> (foo);
+}
valaforeachstatement.vala \
valaforstatement.vala \
valagirparser.vala \
+ valagenericdestroyfield.vala \
+ valagenericdupfield.vala \
valagenerictype.vala \
valagenieparser.vala \
valageniescanner.vala \
--- /dev/null
+/* valagenericdestroyfield.vala
+ *
+ * Copyright (C) 2019 Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Rico Tzschichholz <ricotz@ubuntu.com>
+ */
+
+/**
+ * Represents the Generic.destroy field.
+ */
+public class Vala.GenericDestroyField : Field {
+ /**
+ * Creates a new generic destroy field.
+ *
+ * @return newly created field
+ */
+ public GenericDestroyField (SourceReference source_reference) {
+ base ("destroy", CodeContext.get ().analyzer.delegate_target_destroy_type, null, source_reference);
+ external = true;
+ }
+}
--- /dev/null
+/* valagenericdupfield.vala
+ *
+ * Copyright (C) 2019 Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Rico Tzschichholz <ricotz@ubuntu.com>
+ */
+
+/**
+ * Represents the Generic.dup field.
+ */
+public class Vala.GenericDupField : Field {
+ /**
+ * Creates a new generic dup field.
+ *
+ * @return newly created field
+ */
+ public GenericDupField (SourceReference source_reference) {
+ base ("dup", CodeContext.get ().analyzer.generics_dup_func_type, null, source_reference);
+ external = true;
+ }
+}
*/
public weak TypeParameter type_parameter { get; set; }
+ GenericDupField? dup_field;
+ GenericDestroyField? destroy_field;
+
public GenericType (TypeParameter type_parameter) {
this.type_parameter = type_parameter;
// type parameters are always considered nullable
}
public override Symbol? get_member (string member_name) {
+ if (member_name == "dup") {
+ return get_dup_field ();
+ } else if (member_name == "destroy") {
+ return get_destroy_field ();
+ }
return null;
}
+
+ unowned GenericDupField get_dup_field () {
+ if (dup_field == null) {
+ dup_field = new GenericDupField (source_reference);
+ dup_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return dup_field;
+ }
+
+ unowned GenericDestroyField get_destroy_field () {
+ if (destroy_field == null) {
+ destroy_field = new GenericDestroyField (source_reference);
+ destroy_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return destroy_field;
+ }
}
}
}
+ if (inner is MemberAccess && inner.symbol_reference is TypeParameter) {
+ inner.value_type = new GenericType ((TypeParameter) inner.symbol_reference);
+ inner.value_type.source_reference = source_reference;
+ }
+
if (symbol_reference == null && inner.value_type != null) {
if (pointer_member_access) {
symbol_reference = inner.value_type.get_pointer_member (member_name);
public Class gsource_type;
public DataType delegate_target_type;
public DelegateType delegate_target_destroy_type;
+ public DelegateType generics_dup_func_type;
Delegate destroy_notify;
delegate_target_type = new StructValueType ((Struct) glib_ns.scope.lookup ("pointer"));
destroy_notify = (Delegate) glib_ns.scope.lookup ("DestroyNotify");
delegate_target_destroy_type = new DelegateType (destroy_notify);
+
+ generics_dup_func_type = new DelegateType ((Delegate) glib_ns.scope.lookup ("BoxedCopyFunc"));
} else {
delegate_target_type = new PointerType (new VoidType ());
destroy_notify = new Delegate ("ValaDestroyNotify", new VoidType ());