[julia-users] Re: N in NTuple not enforced

2014-11-28 Thread Andrew Dolgert
I didn't know about NTuple. It's not a typical TypeConstructor, made with 
typealias. It's a core type, implemented in jltypes.c, and you've found a 
bug. Let's look more closely.

julia> snoop(x)=(println(x, " ", typeof(x)); x)
julia> type ftest{T}
 data::f(NTuple{T,Int})
  end
NTuple{T,Int64} DataType
NTuple{T,Int64} DataType

julia> x=ftest{2}((1,2)) # This is how it normally works.
(Int64,Int64) (DataType,DataType)

julia> x=ftest{Float64}((1,2)) # And the goof.
NTuple{Float64,Int64} DataType
julia> x.data
(1,2)

There is a loop in jl_type_intersect 
,
 
where it finds the length of the tuple. It initializes to the length of the 
actual tuple, then looks for a length, and doesn't throw an error if it 
fails to find one. It's my first time looking there, but, you know, HTH.

Drew


Re: [julia-users] Re: N in NTuple not enforced

2014-11-29 Thread Stefan Karpinski
Sound analysis. Care to take a crack at a fix since you've gotten this far? You 
might end up as contributor #300 :-)


> On Nov 29, 2014, at 1:03 AM, Andrew Dolgert  wrote:
> 
> I didn't know about NTuple. It's not a typical TypeConstructor, made with 
> typealias. It's a core type, implemented in jltypes.c, and you've found a 
> bug. Let's look more closely.
> 
> julia> snoop(x)=(println(x, " ", typeof(x)); x)
> julia> type ftest{T}
>  data::f(NTuple{T,Int})
>   end
> NTuple{T,Int64} DataType
> NTuple{T,Int64} DataType
> 
> julia> x=ftest{2}((1,2)) # This is how it normally works.
> (Int64,Int64) (DataType,DataType)
> 
> julia> x=ftest{Float64}((1,2)) # And the goof.
> NTuple{Float64,Int64} DataType
> julia> x.data
> (1,2)
> 
> There is a loop in jl_type_intersect, where it finds the length of the tuple. 
> It initializes to the length of the actual tuple, then looks for a length, 
> and doesn't throw an error if it fails to find one. It's my first time 
> looking there, but, you know, HTH.
> 
> Drew


Re: [julia-users] Re: N in NTuple not enforced

2014-11-29 Thread Andrew Dolgert
Apparently I was wanting something to do. I'll fix it. - Drew



Re: [julia-users] Re: N in NTuple not enforced

2014-11-30 Thread Andreas Noack
Hi Drew

Thanks for the explanation. I didn't know the snoop trick.

Andreas

2014-11-29 12:35 GMT-05:00 Andrew Dolgert :

> Apparently I was wanting something to do. I'll fix it. - Drew
>
>


Re: [julia-users] Re: N in NTuple not enforced

2014-11-30 Thread Drew Dolgert
You figured out that I had a typo where I renamed f() to snoop(). If you're 
interested in how Julia deals with types, and you may not be, forget the 
weird function-on-the-right thing, and take a look at code_lowered() and 
code_typed().

Most of the bug you found happens during a call to typeintersect, which 
finds the common subtype of two given types. First look at normal 
operation. The call happens twice, once in the definition of the type 
test{T}, when T is a TypeVar, and once when T is an Int.
julia> T=TypeVar(:T, true)
julia> h()=typeintersect(NTuple{T,Int},(Int,Int))
julia> g()=typeintersect(NTuple{2,Int},(Int,Int))

What you found, we'll call f().
julia> f()=typeintersect(NTuple{Float64,Int},(Int,Int))
Now, for each of these, look at code_lowered() and code_typed(), and you'll 
see that substitution happens at earlier steps when there isn't a TypeVar.

julia> code_lowered(f,())
julia> code_typed(f,())
julia> code_llvm(f, ())

NTuple is a strange beast. It isn't a TypeConstructor, such as you would 
form with "typealias IntDict{V} Dict{Int,V}". It isn't a normal parametric 
type either, because it compares with a tuple, but when it becomes a tuple 
depends on when you ask.

In short, my suggested fix was dead wrong and breaks hoards of unit tests. 
I'm learning a lot, but you get all the blame. :)

- Drew