Surprising behavior of singleton types

144 views
Skip to first unread message

David Moon

unread,
May 31, 2014, 10:31:54 AM5/31/14
to julia...@googlegroups.com
The manual says Type{xxx} matches only the object xxx, but it does not seem to be true.  Maybe this is related to my post yesterday "Reflection bug for parameterized types?" because this could be another case of confusion between the TypeVars declared in a parameterized type declaration and TypeVars used to instantiate a parameterized type.

Here is an example, run in Julia 0.3:

julia> begin
         f{t,n}(::Type{Array{t}}, ::Array{t,n}) = (t,n,1)
         f{t,n}(::Type{Array{t,n}}, ::Array{t,n}) = (t,n,2)
       end
julia> methods(f)
# 2 methods for generic function "f":
f{t,n}(::Type{Array{t,n}},::Array{t,n}) at none:3
f{t,n}(::Type{Array{t,N}},::Array{t,n}) at none:2

julia> f(Array{Int,1}, [1,2,3])
(Int32,1,2)

julia> f(Array{Int}, [1,2,3])
(Int32,1,2)  # I was expecting (Int32,1,1) !

julia> Array{Int} == Array{Int,1}
false

So Type{Array{t,n}} with t=Int and n=1 matches Array{Int} even though Array{Int,1} and Array{Int} are not the same object!

This only happens when the methods have more than one argument and there are static parameters shared between the Type{...} argument and another argument.  Otherwise Type{Array{t}} only matches Array with only one parameter specified, as expected.

The first method appears to be unreachable.  This means, for example, that the predefined method convert{T,n,S}(::Type{Array{T}}, x::Array{S,n}) in base/array.jl can never be called; convert{T,n,S}(::Type{Array{T,n}}, x::Array{S,n}) will be called instead.  It doesn't appear that anything breaks because of that, but clearly method dispatch is not working the way the author of that code expected.

I didn't search for a pre-existing bug about this, because it's kind of hard to search when the only search key you have is a generic word like "type."

Should I file a bug for this?  Or is it supposed to behave like this and the manual is just wrong?

Iain Dunning

unread,
May 31, 2014, 1:08:29 PM5/31/14
to julia...@googlegroups.com
I don't really know exactly what is going on here, but I'm not sure equality works like that for types, better to use <:

julia> Array{Int} <: Array{Int,1}
false

julia> Array{Int,1} <: Array{Int}
true

And I don't necessarily think this is wrong - look at the code it generates
f{t,n}(::Type{Array{t,n}},::Array{t,n}) at none:3
f{t,n}(::Type{Array{t,N}},::Array{t,n}) at none:2

There is nothing to distinguish these two from a dispatch perspective - its just picking the one defined last.

I think you might be right about that code in Base being unreachable.

Which part of the manual is wrong?

Cheers,
Iain

David Moon

unread,
May 31, 2014, 9:01:46 PM5/31/14
to julia...@googlegroups.com
On Saturday, May 31, 2014 1:08:29 PM UTC-4, Iain Dunning wrote:
And I don't necessarily think this is wrong - look at the code it generates
f{t,n}(::Type{Array{t,n}},::Array{t,n}) at none:3
f{t,n}(::Type{Array{t,N}},::Array{t,n}) at none:2

There is nothing to distinguish these two from a dispatch perspective - its just picking the one defined last.

n ≠ N

This is the bug I mentioned yesterday where Array{T} reads back as Array{T, N}.

Or maybe I didn't understand what you meant by a dispatch perspective.

I checked that reversing the order of the arguments doesn't change this, so it's not an issue of the order of resolving static parameters.

Which part of the manual is wrong?

The part that says Type{xxx} matches only the object xxx.

Jameson Nash

unread,
Jun 1, 2014, 1:59:37 AM6/1/14
to julia...@googlegroups.com



> This is the bug I mentioned yesterday where Array{T} reads back as Array{T, N}.

Array{T} and Array{T,N} describe the same type object


Reply all
Reply to author
Forward
0 new messages