Improve error output for incompatible CallableType (DelegateType, MethodType, SignalType)
Consider this example:
public delegate void callback_t (int x);
public void call_it (callback_t fn) {
fn (123);
}
public class Test {
public void member_method (int x) {
message ("%d\n", x);
}
}
public static int main (string[] args) {
var t = new Test();
call_it (t.member_method); // works
Posix.signal (Posix.Signal.HUP, t.member_method); // fails
return 0;
}
Compiling the above (tested with valac
0.40.16) fails with this error:
test.vala:16.35-16.49: error: Argument 2: Cannot convert from `void Test.member_method (int)' to `void Posix.sighandler_t? (int)'
Posix.signal (Posix.Signal.HUP, t.member_method);
^^^^^^^^^^^^^^^
Notice that passing the member method to call_it ()
works fine, but fails when invoking Posix.signal ()
. Worse, valac
tells me that a method with that signature can't be converted to a method with essentially the same exact signature?
After some digging in the generated code, it's clear that Posix.signal ()
is literally just invoking the underlying POSIX signal()
call, which expects a function pointer conforming to void(*)(int)
; since member_method
is bound to a class instance and needs to receive a pointer to self
, instead, an intermediate method gets generated which looks like this instead:
static void _test_member_method_callback_t (gint x,
gpointer self);
This is clearly incompatible with what the POSIX signal()
call expects, so it fails. The only reason it works for call_it ()
is that valac
is able to modify its signature in the generated code so to pass around the pointer to the class instance, while this is obviously not possible with signal()
.
The problem here is that the message coming from the compiler makes absolutely no effort in indicating why the conversion would be failing, and how to repair that. Please consider some work on improving the error reporting.
(To be noted that I'm using Posix.signal ()
as an example as that's where I have encountered this issue, but it sounds like could occur when passing around member methods as delegates for any VAPI-wrapped C API.)