From: Rico Tzschichholz Date: Mon, 10 Jul 2023 20:13:29 +0000 (+0200) Subject: vala: Improve check for compatibility of method and delegate with generics X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0be8eac389cc025e62d5c4fac7e43d275d91f031;p=thirdparty%2Fvala.git vala: Improve check for compatibility of method and delegate with generics --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 433ad35fc..41f293c1f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..725992316 --- /dev/null +++ b/tests/generics/method-to-delegate-2.c-expected @@ -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 +#include +#include + +#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 index 000000000..0d61667bd --- /dev/null +++ b/tests/generics/method-to-delegate-2.vala @@ -0,0 +1,23 @@ +delegate void Func (G g); + +void foo (string s) { + assert (s == "foo"); +} + +void call_foo (Func f) { + f ("foo"); +} + +void bar (int i) { + assert (i == 42); +} + +void call_bar (Func 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 index 000000000..d0a883f20 --- /dev/null +++ b/tests/generics/method-to-delegate-incompatible-2.test @@ -0,0 +1,13 @@ +Invalid Code + +delegate void FooFunc (string s); + +void bar (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 index 000000000..de82f0c00 --- /dev/null +++ b/tests/generics/method-to-delegate-incompatible-3.test @@ -0,0 +1,10 @@ +Invalid Code + +delegate void FooFunc (G g); + +void foo (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 index 000000000..5b61d6b5d --- /dev/null +++ b/tests/generics/method-to-delegate-incompatible.test @@ -0,0 +1,10 @@ +Invalid Code + +delegate void FooFunc (string s); + +void foo (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 index 000000000..86f8eb185 --- /dev/null +++ b/tests/generics/method-to-delegate.c-expected @@ -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 +#include +#include + +#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 index 000000000..8d415db86 --- /dev/null +++ b/tests/generics/method-to-delegate.vala @@ -0,0 +1,18 @@ +delegate void Func (G g); + +void foo (string s) { + assert (s == "foo"); +} + +void bar (int i) { + assert (i == 42); +} + +void main () { + Func f = foo; + f ("foo"); + + Func b; + b = bar; + b (42); +} diff --git a/vala/valamethodtype.vala b/vala/valamethodtype.vala index 76641b041..a20f345cb 100644 --- a/vala/valamethodtype.vala +++ b/vala/valamethodtype.vala @@ -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); }