Tell the compiler that two code paths yield the same type

Every now and then I have code like this:

function calculate_or_lookup(...)
    if iscached(...)
        return load_from_cache(...) # cheap
    else
        return calculate(...) # expensive
    end
end

As a programmer I know that calculate and load_from_cache will yield the same type.
Often the compiler can only infer the type of calculate and has no chance to know the return type of load_from_cache. Is there a way to tell the compiler that calculate_or_lookup has the same return type as calculate?

load_from_cache(...)::KnownType

Yeah often KnownType is a three line long ugly beast with 20 parameters that depend on the input argument types :smiley:

Does the cache know the type it contains? If so, you can assert the type in the loading function.

You could use Core.Compiler.return_type for this:

function calculate_or_lookup(...)
    if iscached(...)
        return load_from_cache(...) # cheap
    else
        return calculate(...)::Core.Compiler.return_type(load_from_cache, Tuple{#= argument types for `load_from_cache` =#})
    end
end

although I would first benchmark whether this is actually worth it. Dynamic dispatch is not that expensive as long as it isn’t used in a hot loop, so just adding @nospecialize to calculate_or_lookup to avoid overly specializing and just relying on dynamic dispatch may well be an option.

3 Likes