Incorrect ambiguity?

I’m trying to understand why the following gives an ambiguity error both on 0.5 and 0.6:

foo{T<:Number}(::Bool, ::T) = 1
foo{S<:Symbol}(::Union{S,Real}, ::Union{S,Real}) = 1

foo(true,4.) #ambiguity error here

While it might seem like this call matches both definitions, if actually doesn’t match the second one because the S parameter is not captured. You can check by deleting the first definition, you’ll get a “no method matching foo” when you call foo(true,4.). Therefore, there should be no ambiguity since only the first method matches, right? Is this perhaps a bug?

Fyi, I’m running into this with the definition in bool.jl for *{T<:Number}(::Bool, ::T) = ...

The uncaptured type parameters aren’t handled consistently. It’s likely that we’ll make the second one match.

Interesting, thanks. FWIW, in the short time since I first realized the second one doesn’t match, I’ve grown to like that it doesn’t. For example, it lets you match “at least one arg of abstract type Foo, and maybe some of type Bar” via,

f(::Union{F,Foo,Bar}...) where {F<:Foo} = ...

Would matching something like this still be possible after making methods match even with uncaptured parameters? Also, what would be the value of the uncaptured parameter in the function then?

1 Like

It would be really cool if uncaptured (as well as captured) parameters could simply be specified in the function call, as in foo{Bool}(true,4.) or foo{Symbol}(true,4.), to disambiguate above. This would also provide a much more concise dispatch-on-constant mechanism than value types. For example, today we can do:

f{x}(::Type{Val{x}},y) = x*y
f(Val{0}, a) # compiled as 0*a and might be optimized to 0.

It would be neat to get the same effect with:

f{x}(y) = x*y
f{0}(a)

Today, the first line gives a warning that “the method will not be callable” and the second one gives an error. But it is quite possible that this collides with some part of julia syntax that I haven’t thought about.

(This was of course a simple example, and f would probably be inlined and optimized anyway, but larger or recursive functions might not be.)