Hi,
GTK4 has a lot of GObject interfaces that are mapped to Crystal modules in the bindings, but it also has a lot of callbacks that receives that interfaces as parameters or return types, so I create aliases for these callbacks like:
alias TreeListModelCreateModelFunc = Proc(GObject::Object, Gio::ListModel?)
Where Gio::ListModel
is a interface (i.e. a Crystal module).
The problem rises when I try to use functions that receive these callbacks as parameters… summarizing the problem in plain Crystal code:
module Interface
end
class Implementation
include Interface
end
alias Callback = Proc(Interface?)
def callback_impl : Interface?
# If I comment the line above it also doesn't works.
Implementation.new if rand < 0.5
end
def callback_caller(callback : Callback) : Interface?
callback.call
end
callback_caller(->callback_impl)
This error out with:
expected argument #1 to 'callback_caller' to be Proc((Interface | Nil)), not Proc((Implementation | Nil))
Overloads are:
- callback_caller(callback : Callback)
I remember that return type restrictions as the name says are just restrictions… basically used only to generate error messages, not to define the return type.
So the only way to fix that is rewriting the callback with a ugly cast:
def callback_impl : Interface?
# If I comment the line above it also doesn't works.
Implementation.new.as(Interface) if rand < 0.5
end
Now the question
What was the reason to keep return type restriction just a… restriction, not the real method return type, and what would be the consequences of changing this (besides API breakage).