]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Improve check for compatibility of method and delegate with generics
authorRico Tzschichholz <ricotz@ubuntu.com>
Mon, 10 Jul 2023 20:13:29 +0000 (22:13 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 10 Jul 2023 20:13:29 +0000 (22:13 +0200)
tests/Makefile.am
tests/generics/method-to-delegate-2.c-expected [new file with mode: 0644]
tests/generics/method-to-delegate-2.vala [new file with mode: 0644]
tests/generics/method-to-delegate-incompatible-2.test [new file with mode: 0644]
tests/generics/method-to-delegate-incompatible-3.test [new file with mode: 0644]
tests/generics/method-to-delegate-incompatible.test [new file with mode: 0644]
tests/generics/method-to-delegate.c-expected [new file with mode: 0644]
tests/generics/method-to-delegate.vala [new file with mode: 0644]
vala/valamethodtype.vala

index 433ad35fcbab08c94b37d6b7430ed68b6fff522a..41f293c1f7fd4de89af686b72eb04b8649ffdb49 100644 (file)
@@ -822,6 +822,11 @@ TESTS = \
        generics/method-return-type-missing.test \
        generics/method-return-unknown-type-parameter.test \
        generics/method-return-unknown-type-parameter-2.test \
+       generics/method-to-delegate.vala \
+       generics/method-to-delegate-2.vala \
+       generics/method-to-delegate-incompatible.test \
+       generics/method-to-delegate-incompatible-2.test \
+       generics/method-to-delegate-incompatible-3.test \
        generics/null-type.vala \
        generics/property-gobject-set.vala \
        generics/property-int-cast.vala \
diff --git a/tests/generics/method-to-delegate-2.c-expected b/tests/generics/method-to-delegate-2.c-expected
new file mode 100644 (file)
index 0000000..7259923
--- /dev/null
@@ -0,0 +1,91 @@
+/* generics_method_to_delegate_2.c generated by valac, the Vala compiler
+ * generated from generics_method_to_delegate_2.vala, do not modify */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.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
+
+typedef void (*Func) (gconstpointer g, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN void foo (const gchar* s);
+VALA_EXTERN void call_foo (Func f,
+               gpointer f_target);
+VALA_EXTERN void bar (gint i);
+VALA_EXTERN void call_bar (Func f,
+               gpointer f_target);
+static void _vala_main (void);
+static void _foo_func (gconstpointer g,
+                gpointer self);
+static void _bar_func (gconstpointer g,
+                gpointer self);
+
+void
+foo (const gchar* s)
+{
+       g_return_if_fail (s != NULL);
+       _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\"");
+}
+
+void
+call_foo (Func f,
+          gpointer f_target)
+{
+       f ("foo", f_target);
+}
+
+void
+bar (gint i)
+{
+       _vala_assert (i == 42, "i == 42");
+}
+
+void
+call_bar (Func f,
+          gpointer f_target)
+{
+       f ((gpointer) ((gintptr) 42), f_target);
+}
+
+static void
+_foo_func (gconstpointer g,
+           gpointer self)
+{
+       foo ((const gchar*) g);
+}
+
+static void
+_bar_func (gconstpointer g,
+           gpointer self)
+{
+       bar ((gint) ((gintptr) g));
+}
+
+static void
+_vala_main (void)
+{
+       call_foo (_foo_func, NULL);
+       call_bar (_bar_func, NULL);
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/generics/method-to-delegate-2.vala b/tests/generics/method-to-delegate-2.vala
new file mode 100644 (file)
index 0000000..0d61667
--- /dev/null
@@ -0,0 +1,23 @@
+delegate void Func<G> (G g);
+
+void foo (string s) {
+       assert (s == "foo");
+}
+
+void call_foo (Func<string> f) {
+       f ("foo");
+}
+
+void bar (int i) {
+       assert (i == 42);
+}
+
+void call_bar (Func<int> f) {
+       f (42);
+}
+
+void main () {
+       call_foo (foo);
+
+       call_bar (bar);
+}
diff --git a/tests/generics/method-to-delegate-incompatible-2.test b/tests/generics/method-to-delegate-incompatible-2.test
new file mode 100644 (file)
index 0000000..d0a883f
--- /dev/null
@@ -0,0 +1,13 @@
+Invalid Code
+
+delegate void FooFunc (string s);
+
+void bar<G> (G g) {
+}
+
+void foo (FooFunc f) {
+}
+
+void main () {
+       foo (bar);
+}
diff --git a/tests/generics/method-to-delegate-incompatible-3.test b/tests/generics/method-to-delegate-incompatible-3.test
new file mode 100644 (file)
index 0000000..de82f0c
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+delegate void FooFunc<G> (G g);
+
+void foo<G> (G g) {
+}
+
+void main () {
+       FooFunc f = foo;
+}
diff --git a/tests/generics/method-to-delegate-incompatible.test b/tests/generics/method-to-delegate-incompatible.test
new file mode 100644 (file)
index 0000000..5b61d6b
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+delegate void FooFunc (string s);
+
+void foo<G> (G g) {
+}
+
+void main () {
+       FooFunc f = foo;
+}
diff --git a/tests/generics/method-to-delegate.c-expected b/tests/generics/method-to-delegate.c-expected
new file mode 100644 (file)
index 0000000..86f8eb1
--- /dev/null
@@ -0,0 +1,97 @@
+/* generics_method_to_delegate.c generated by valac, the Vala compiler
+ * generated from generics_method_to_delegate.vala, do not modify */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.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
+
+typedef void (*Func) (gconstpointer g, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN void foo (const gchar* s);
+VALA_EXTERN void bar (gint i);
+static void _vala_main (void);
+static void _foo_func (gconstpointer g,
+                gpointer self);
+static void _bar_func (gconstpointer g,
+                gpointer self);
+
+void
+foo (const gchar* s)
+{
+       g_return_if_fail (s != NULL);
+       _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\"");
+}
+
+void
+bar (gint i)
+{
+       _vala_assert (i == 42, "i == 42");
+}
+
+static void
+_foo_func (gconstpointer g,
+           gpointer self)
+{
+       foo ((const gchar*) g);
+}
+
+static void
+_bar_func (gconstpointer g,
+           gpointer self)
+{
+       bar ((gint) ((gintptr) g));
+}
+
+static void
+_vala_main (void)
+{
+       Func f = NULL;
+       gpointer f_target;
+       GDestroyNotify f_target_destroy_notify;
+       Func b = NULL;
+       gpointer b_target = NULL;
+       GDestroyNotify b_target_destroy_notify = NULL;
+       f = _foo_func;
+       f_target = NULL;
+       f_target_destroy_notify = NULL;
+       f ("foo", f_target);
+       (b_target_destroy_notify == NULL) ? NULL : (b_target_destroy_notify (b_target), NULL);
+       b = NULL;
+       b_target = NULL;
+       b_target_destroy_notify = NULL;
+       b = _bar_func;
+       b_target = NULL;
+       b_target_destroy_notify = NULL;
+       b ((gpointer) ((gintptr) 42), b_target);
+       (b_target_destroy_notify == NULL) ? NULL : (b_target_destroy_notify (b_target), NULL);
+       b = NULL;
+       b_target = NULL;
+       b_target_destroy_notify = NULL;
+       (f_target_destroy_notify == NULL) ? NULL : (f_target_destroy_notify (f_target), NULL);
+       f = NULL;
+       f_target = NULL;
+       f_target_destroy_notify = NULL;
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/generics/method-to-delegate.vala b/tests/generics/method-to-delegate.vala
new file mode 100644 (file)
index 0000000..8d415db
--- /dev/null
@@ -0,0 +1,18 @@
+delegate void Func<G> (G g);
+
+void foo (string s) {
+       assert (s == "foo");
+}
+
+void bar (int i) {
+       assert (i == 42);
+}
+
+void main () {
+       Func f = foo;
+       f ("foo");
+
+       Func<int> b;
+       b = bar;
+       b (42);
+}
index 76641b041522666898dc933d7440bc6f0a20833c..a20f345cbd1fa5c17dc712e2afb42db573309b4a 100644 (file)
@@ -47,6 +47,12 @@ public class Vala.MethodType : CallableType {
                        return false;
                }
 
+               // FIXME delegates don't provide dedicated parameters for generic arguments,
+               // therefore they are never compatible
+               if (!(method_symbol.parent_node is LambdaExpression) && method_symbol.has_type_parameters ()) {
+                       return false;
+               }
+
                return dt.delegate_symbol.matches_method (method_symbol, dt);
        }