Argument types not inferred when constrained in function signature

It is a curious case when I tried to see how julia handles type constraints:

julia> f(a::A, b::B) where{B<:Tuple{C}} where {A,C<:A} = (A, B, C)
f (generic function with 1 method)

julia> @code_warntype f(1, (2,))
Body::Tuple{DataType,DataType,DataType}
1 ─ %1 = (Core.tuple)($(Expr(:static_parameter, 1)), $(Expr(:static_parameter, 3)), $(Expr(:static_parameter, 2)))::Core.Compiler.Const((Int64, Tuple{Int64}, Int64), false)
└──      return %1

julia> @code_warntype f(1, ("2",))
Body::Tuple{Type{A} where A<:Union{Int64, String},DataType,DataType}
1 ─ %1 = (Core.tuple)($(Expr(:static_parameter, 1)), $(Expr(:static_parameter, 3)), $(Expr(:static_parameter, 2)))::Core.Compiler.PartialTuple(Tuple{Type{A} where A<:Union{Int64, String},DataType,DataType}, Any[Type{A} where A<:Union{Int64, String}, Const(Tuple{String}, false), Const(String, false)])
└──      return %1

julia> f(1, ("2",)) # can be (Any, Tuple{Int}, Int) ?
ERROR: UndefVarError: A not defined
Stacktrace:
 [1] f(::Int64, ::Tuple{String}) at ./REPL[1]:1
 [2] top-level scope at none:0

Same on master and v1.0.3.
Is it a bug? Or better error message needed?

 f(a::A, b::B) where{A, C<:A, B<:Tuple{C}} = (A, B, C)

Edit: this is not a fix

That does not work for me. Did you try f(1,("2",)) ? What julia version are you on?

Oops sorry, I tried it on (1, (2,)) but yours also works there. Mine doesn’t work on (1, ("2",)).

This doesn’t feel like a bug to me but the error message is in any case strange.

2 Likes

It could be, but it’s not a unique solution. The static-parameters only get assigned a value if they are uniquely constrained (sorry, I’m not immediately sure where to point to documentation of this). There’s been a call for more informative error messages for related cases, if someone wanted to investigate further (Better error messages for UndefVarError · Issue #29313 · JuliaLang/julia · GitHub)

1 Like