Julia v1.1 Language changes: ambiguities


  • Method signatures such as f(::Type{T}, ::T) where {T <: X} and f(::Type{X}, ::Any) are now considered ambiguous. Previously a bug caused the first one to be considered more specific in some cases (#30160).

Should the f(::Type{T}, ::T) where {T <: X} be f(::Type{T}, ::Any) where {T <: X}, change the second argument from ::T to ::Any

1 Like

No, I believe that description is correct — it matches the tests that were added in the same commit.

1 Like

I am thinking that “the first one to be considered more specific” is more understandable.
Would you please explain why the change?

I’m perhaps not the best person to do so, but I reason about this as a case where one arg is more specific and the other arg is less specific. In this concrete case:

f(::Type{T}, ::T) where {T<:BitArray} = 1
f(::Type{BitArray}, ::Any) = 2

julia> f(BitArray, trues(3))
ERROR: MethodError: f(::Type{BitArray}, ::BitArray{1}) is ambiguous. Candidates:
  f(::Type{BitArray}, ::Any) in Main at REPL[2]:1
  f(::Type{T}, ::T) where T<:BitArray in Main at REPL[1]:1
Possible fix, define
  f(::Type{BitArray}, ::BitArray)

In other circumstances, ::Type{BitArray} is more specific than ::Type{T} where {T <: BitArray}:

g(::Type{BitArray}) = 1
g(::Type{T}) where {T<:BitArray} = 2

julia> g(BitArray)

But the ::Any is less specific than the matching ::T. Thus we have an ambiguity — one argument is more specific but the other is less.


The test case added in the pull request seems to make the issue fairly clear:

The method specificity relation really ought to be a partial order, and in particular, it should be transitive. There are certain cases where it fails to be transitive, and this change fixes one of those failures of transitivity. Was there a specific reason you were concerned about this change? Do you have code that is affected by it?

1 Like

Thanks for the reply!
I am a beginner, no code affected by this.
I just like to know a bit (if possible) on the ‘counter-intuitive’ points.