@@ -941,13 +941,44 @@ function method_exists(f::ANY, t::ANY)
941
941
typemax (UInt)) != 0
942
942
end
943
943
944
+ """
945
+ isambiguous(m1, m2, [allow_bottom_tparams=true]) -> Bool
946
+
947
+ Determine whether two methods `m1` and `m2` (typically of the same
948
+ function) are ambiguous. This test is performed in the context of
949
+ other methods of the same function; in isolation, `m1` and `m2` might
950
+ be ambiguous, but if a third method resolving the ambiguity has been
951
+ defined, this returns `false`.
952
+
953
+ For parametric types, `allow_bottom_tparams` controls whether
954
+ `Union{}` is considered a valid intersection of type parameters. For example:
955
+ ```julia
956
+ julia> foo(x::Complex{<:Integer}) = 1
957
+ foo (generic function with 1 method)
958
+
959
+ julia> foo(x::Complex{<:Rational}) = 2
960
+ foo (generic function with 2 methods)
961
+
962
+ julia> m1, m2 = collect(methods(foo))
963
+ 2-element Array{Any,1}:
964
+ foo(x::Complex{#s1} where #s1<:Integer) in Main at REPL[1]:1
965
+ foo(x::Complex{#s1} where #s1<:Rational) in Main at REPL[2]:1
966
+
967
+ julia> typeintersect(m1.sig, m2.sig)
968
+ Tuple{#foo,Complex{Union{}}}
969
+
970
+ julia> Base.isambiguous(m1, m2, true)
971
+ true
972
+
973
+ julia> Base.isambiguous(m1, m2, false)
974
+ false
975
+ ```
976
+ """
944
977
function isambiguous (m1:: Method , m2:: Method , allow_bottom_tparams:: Bool = true )
945
978
ti = typeintersect (m1. sig, m2. sig)
946
979
ti === Bottom && return false
947
980
if ! allow_bottom_tparams
948
- (_, env) = ccall (:jl_match_method , Ref{SimpleVector}, (Any, Any),
949
- ti, m1. sig)
950
- any (x-> x === Bottom, env) && return false
981
+ has_bottom_parameter (ti) && return false
951
982
end
952
983
ml = _methods_by_ftype (ti, - 1 , typemax (UInt))
953
984
isempty (ml) && return true
@@ -959,6 +990,23 @@ function isambiguous(m1::Method, m2::Method, allow_bottom_tparams::Bool=true)
959
990
return true
960
991
end
961
992
993
+ """
994
+ has_bottom_parameter(t) -> Bool
995
+
996
+ Determine whether `t` is a Type for which one or more of its parameters is `Union{}`.
997
+ """
998
+ function has_bottom_parameter (t:: Type )
999
+ ret = false
1000
+ for p in t. parameters
1001
+ ret |= (p == Bottom) || has_bottom_parameter (p)
1002
+ end
1003
+ ret
1004
+ end
1005
+ has_bottom_parameter (t:: UnionAll ) = has_bottom_parameter (unwrap_unionall (t))
1006
+ has_bottom_parameter (t:: Union ) = has_bottom_parameter (t. a) & has_bottom_parameter (t. b)
1007
+ has_bottom_parameter (t:: TypeVar ) = has_bottom_parameter (t. ub)
1008
+ has_bottom_parameter (:: Any ) = false
1009
+
962
1010
min_world (m:: Method ) = reinterpret (UInt, m. min_world)
963
1011
max_world (m:: Method ) = reinterpret (UInt, m. max_world)
964
1012
min_world (m:: Core.MethodInstance ) = reinterpret (UInt, m. min_world)
0 commit comments