How to check what method is used by dispatch?

Hey,

Say I have an abstract type A and many subtypes B, C, D:

abstract type A end
struct B<:A end
struct C<:A end

should_return_one(::A) = 1
should_return_one(x::B) = # something else. 
# remark that, on purpose, I did not overwrote the method for x::C

Suppose now that for testing reasons, I want to ensure that the subtypes are implementing the method correctly. I am testing it like that :

objects = (B(), C()) # there are a lot more objects here. 
for o in objets 
    @test should_return_one(o) == 1
end

Now, if the method is very costly, testing the method for C is not worth it because it will dispatch to the generic version. Thus, I’d like to only test when object do indeed overwrite the generic method:

objects = (B(), C()) # there are a lot more objects here. 
for o in objets
    condition = # the call will not dispatch to should_return_one(::A)
    if condition
        @test should_return_one(o) == 1
    end
end

How can i write this condition ?

Hopefully there are better ways to do this, but one option is to use which and check the (internal, private, unreliable, use at your own risk) field sig:

julia> using Test, InteractiveUtils

julia> abstract type A end

julia> struct B<:A end

julia> struct C<:A end

julia> should_return_one(::A) = 1
should_return_one (generic function with 2 methods)

julia> should_return_one(x::B) = 2
should_return_one (generic function with 2 methods)

julia> which(should_return_one, (B,)).sig
Tuple{typeof(should_return_one), B}

julia> which(should_return_one, (C,)).sig
Tuple{typeof(should_return_one), A}

How, which sound nice indeed… What about simply which(should_return_one, (A,)) == which(should_return_one, (B,)) ? To avoid internals.

I guess that’d work (I didn’t realise which accepts abstract types, but it’s documented to do so, that’s good)

1 Like