I was trying out some things in the Julia (1.2) REPL and I stuck my mind on something I don't understand about dispatching.
I first tried this thing which is working the way I expected:
f(a::T) where {T <: Int} = "Test"
Calling f(3) works since
Int <: Int == true
Calling f("Hello") results in an "MethodError: no method matching" error since
String <: Int == false
Then, I tried this method, and I don't understand why calling it works in some case:
f(a::T, b::U) where {T, U <: T} = "Another Test"
Calling f(3, 3) works (as I expected)
BUT f(3, "Hello") also works and does not throw a "MethodError: no method matching" ???
I thought that (since T becomes an Int and U a String) String <: Int == false
???
I guess I am missing something pretty straightforward here but I can't find it... So this is my question, why f(3, "Hello") is working???
Moreover, I tried this snippet of code (i tried to recreate the second method signature) and it correctly fails as I expected:
Test = Tuple{T, U} where {T, U <: T}
Test{Int, String}
(this fails as i expected with "TypeError: in Type, in U, expected U<:Int64, got Type{String}")
Int64,String,false
. You might need to restart Julia if you add methods to functions. Just use a new character e.g.h
for a new test. To your question: It appears that the system tries to find any solution to the type restriction, andT=Any, U=Any where U:<T
is one. If you introduce a concrete type as in your third example it works as expected. People with a sounder Julia type system knowledge will soon give a proper answer to this. – Prosaism