Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stagedfunction-related compilation error when type inference fails #8504

Closed
timholy opened this issue Sep 28, 2014 · 23 comments
Closed

stagedfunction-related compilation error when type inference fails #8504

timholy opened this issue Sep 28, 2014 · 23 comments
Labels
bug Indicates an unexpected problem or unintended behavior priority This should be addressed urgently
Milestone

Comments

@timholy
Copy link
Member

timholy commented Sep 28, 2014

I've found a case where compiling a function that calls a stagedfunction fails, due to a failure in type inference. If one checks out #8501 (and preferably, inserts a println(P) here), here's a simple way to reproduce:

function as_sub(x::AbstractMatrix)
    y = similar(x, eltype(x), tuple(([size(x)...]*2)...))
    @show typeof(y)
    y = sub(y, 2:2:size(y,1), 2:2:size(y,2))
    for j=1:size(x,2)
        for i=1:size(x,1)
            y[i,j] = x[i,j]
        end
    end
    y
end

as_sub(eye(2))

This gives the following output:

julia> as_sub(eye(2))
Array{Float64,N}
Array{Float64,N}
Array{Float64,N}
ERROR: `ndims` has no method matching ndims(::Type{Any})
 in ndims at ./abstractarray.jl:22 (repeats 3 times)
 in setindex! at ./subarray2.jl:35

One can see that it fails at compile-time, not runtime: that @show typeof(y) never gets called.

A modified version of the function (which declares the type of y):

function as_sub1(x::AbstractMatrix)
    y = similar(x, eltype(x), tuple(([size(x)...]*2)...))::typeof(x)
    @show typeof(y)
    y = sub(y, 2:2:size(y,1), 2:2:size(y,2))
    for j=1:size(x,2)
        for i=1:size(x,1)
            y[i,j] = x[i,j]
        end
    end
    y
end

yields this:

julia> as_sub1(eye(2))
Array{Float64,2}
Array{Float64,2}
typeof(y) = Array{Float64,2}
2x2 SubArray{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}:
 1.0  0.0
 0.0  1.0
@timholy
Copy link
Member Author

timholy commented Sep 28, 2014

While waiting for something else to compile, I looked at this again. Seems like it's a bug in our implementation of stagedfunctions, because I can use this to segfault julia (check out & build the teh/subarray branch to test). From inside the test/ folder:

$ gdb julia
GNU gdb (Ubuntu 7.7-0ubuntu3.1) 7.7
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from julia...done.
(gdb) run
Starting program: /home/tim/src/julia/julia 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff128c700 (LWP 4256)]
[New Thread 0x7ffff0a8b700 (LWP 4257)]
[New Thread 0x7fffee28a700 (LWP 4258)]
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "help()" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.4.0-dev+790 (2014-09-28 00:57 UTC)
 _/ |\__'_|_|_|\__'_|  |  teh/subarray/d4cab1d* (fork: 1 commits, 2 days)
|__/                   |  x86_64-linux-gnu

julia> using Base.Test

julia> include("broadcast.jl")
ERROR: test error in expression: broadcast(+,arr(eye(2)),arr([1,4])) == [2 1;4 5]
`ndims` has no method matching ndims(::Type{Any})
 in ndims at ./abstractarray.jl:22 (repeats 3 times)
 in setindex! at ./subarray2.jl:34
 in anonymous at ./test.jl:83
 in do_test at ./test.jl:47
 in anonymous at ./no file:38
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
while loading /home/tim/src/julia/test/broadcast.jl, in expression starting on line 36

julia> as_sub(eye(2))

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff76292d6 in llvm::MDNode::getOperand(unsigned int) const ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
(gdb) bt
#0  0x00007ffff76292d6 in llvm::MDNode::getOperand(unsigned int) const ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#1  0x00007ffff716342a in llvm::DwarfCompileUnit::createGlobalVariableDIE(llvm::DIGlobalVariable) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#2  0x00007ffff7145855 in llvm::DwarfDebug::beginModule() () from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#3  0x00007ffff71452ae in llvm::DwarfDebug::DwarfDebug(llvm::AsmPrinter*, llvm::Module*) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#4  0x00007ffff7136734 in llvm::AsmPrinter::doInitialization(llvm::Module&) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#5  0x00007ffff7622c8f in llvm::FPPassManager::doInitialization(llvm::Module&) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#6  0x00007ffff7622fc0 in llvm::legacy::PassManagerImpl::run(llvm::Module&) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#7  0x00007ffff749d821 in llvm::MCJIT::emitObject(llvm::Module*) () from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#8  0x00007ffff749da21 in llvm::MCJIT::generateCodeForModule(llvm::Module*) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#9  0x00007ffff749e265 in llvm::MCJIT::getSymbolAddress(std::string const&, bool) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#10 0x00007ffff749f2cc in llvm::LinkingMemoryManager::getSymbolAddress(std::string const&) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#11 0x00007ffff74a297c in llvm::RuntimeDyldImpl::resolveExternalSymbols() ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#12 0x00007ffff74a2679 in llvm::RuntimeDyldImpl::resolveRelocations() ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#13 0x00007ffff749db8c in llvm::MCJIT::finalizeLoadedModules() () from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#14 0x00007ffff749e32a in llvm::MCJIT::getFunctionAddress(std::string const&) ()
   from /home/tim/src/julia/usr/bin/../lib/libjulia-debug.so
#15 0x00007ffff6db37e4 in jl_generate_fptr (f=0x10311d50) at codegen.cpp:667
#16 0x00007ffff6d9b4dc in jl_trampoline_compile_function (f=0x10311d50, always_infer=0, sig=0x684800) at builtins.c:809
#17 0x00007ffff6d9b5de in jl_trampoline (F=0x10311d50, args=0x7fffffffced8, nargs=1) at builtins.c:819
#18 0x00007ffff6d8d494 in jl_apply (f=0x10311d50, args=0x7fffffffced8, nargs=1) at julia.h:989
#19 0x00007ffff6d92c2a in jl_apply_generic (F=0x5f28420, args=0x7fffffffced8, nargs=1) at gf.c:1623
#20 0x00007ffff6e1d1fe in jl_apply (f=0x5f28420, args=0x7fffffffced8, nargs=1) at julia.h:989
#21 0x00007ffff6e1d711 in do_call (f=0x5f28420, args=0x10ce6288, nargs=1, locals=0x0, nl=0) at interpreter.c:65
#22 0x00007ffff6e1e297 in eval (e=0x10ce81b0, locals=0x0, nl=0) at interpreter.c:207
#23 0x00007ffff6e1d359 in jl_interpret_toplevel_expr (e=0x10ce81b0) at interpreter.c:25
#24 0x00007ffff6e3448d in jl_toplevel_eval_flex (e=0x10ce8050, fast=1) at toplevel.c:496
#25 0x00007ffff6e345b7 in jl_toplevel_eval (v=0x10ce8050) at toplevel.c:519
---Type <return> to continue, or q <return> to quit---
#26 0x00007ffff6d99bba in jl_f_top_eval (F=0x2337cb0, args=0x7fffffffd718, nargs=2) at builtins.c:425
#27 0x00007ffff485357a in julia_eval_user_input301179 () at REPL.jl:54
#28 0x00007ffff4853747 in jlcall_eval_user_input301179 ()
#29 0x00007ffff6d8d494 in jl_apply (f=0x55a0330, args=0x7fffffffd948, nargs=2) at julia.h:989
#30 0x00007ffff6d92c2a in jl_apply_generic (F=0xc62170, args=0x7fffffffd948, nargs=2) at gf.c:1623
#31 0x00007ffff7e4e35f in julia_anonymous301080 () at task.jl:96
#32 0x00007ffff6d97e2a in jl_apply (f=0x36fb630, args=0x0, nargs=0) at julia.h:989
#33 0x00007ffff6d9b5f4 in jl_trampoline (F=0x36fb630, args=0x0, nargs=0) at builtins.c:820
#34 0x00007ffff6e284b2 in jl_apply (f=0x36fb630, args=0x0, nargs=0) at julia.h:989
#35 0x00007ffff6e28faf in start_task (t=0x4825390) at task.c:426
#36 0x00007ffff6e28a70 in switch_stack (t=0x4825390, where=0x48253e0) at task.c:207
#37 0x00007ffff6e28ad2 in jl_switch_stack (t=0x4825390, where=0x48253e0) at task.c:217
#38 0x00007ffff6e29030 in jl_handle_stack_switch () at task.c:434
#39 0x00007ffff6e27d66 in julia_trampoline (argc=0, argv=0x7fffffffdd00, pmain=0x4020b7 <true_main>) at init.c:1011
#40 0x0000000000402486 in main (argc=0, argv=0x7fffffffdd00) at repl.c:379
(gdb) 

@timholy
Copy link
Member Author

timholy commented Oct 8, 2014

Using the test script at the top of this issue, valgrind gives me this:

...
==26045== Syscall param msync(start) points to unaddressable byte(s)
==26045==    at 0x5EF7B3D: ??? (syscall-template.S:81)
==26045==    by 0x58A314B: msync_validate (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A3278: validate_mem (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A33B3: access_mem (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A1117: dwarf_get (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A13CE: _ULx86_64_access_reg (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A0CA2: _ULx86_64_get_reg (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A5D46: apply_reg_state (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A6419: _ULx86_64_dwarf_find_save_locs (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A289E: _ULx86_64_dwarf_step (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x58A1563: _ULx86_64_step (in /home/tim/src/julia/usr/lib/libjulia-debug.so)
==26045==    by 0x4F9EA02: rec_backtrace_ctx (task.c:621)
==26045==  Address 0xffeffb000 is not stack'd, malloc'd or (recently) free'd
==26045== 

ERROR: `ndims` has no method matching ndims(::Type{Any})
 in ndims at abstractarray.jl:22 (repeats 3 times)
 in setindex! at subarray2.jl:34
 in include at ./boot.jl:245
 in include_from_node1 at loading.jl:128
 in process_options at ./client.jl:293
 in _start at ./client.jl:362
 in _start_3B_5893 at /home/tim/src/julia/usr/bin/../lib/julia/sys.so
while loading /home/tim/tmp/staged_typeinf.jl, in expression starting on line 13
==26045== 
==26045== HEAP SUMMARY:
==26045==     in use at exit: 93,094,588 bytes in 43,313 blocks
==26045==   total heap usage: 274,602 allocs, 231,289 frees, 174,474,513 bytes allocated
...

No such unaddressable bytes lines appear in a valgrind run where the test script in its entirely is just nothing.

This is new territory for me, but does this suggest a missing GC root or something?

@timholy
Copy link
Member Author

timholy commented Oct 8, 2014

(That's in our usage of unwind, which is scary.)

@Keno
Copy link
Member

Keno commented Oct 8, 2014

As far as I know Syscall param msync(start) points to unaddressable byte(s) is harmless and may be a false positive. In any case, it's always appeared when running julia on linux.

@timholy
Copy link
Member Author

timholy commented Oct 8, 2014

No such unaddressable bytes lines appear in a valgrind run where the test script in its entirely is just nothing.

@timholy
Copy link
Member Author

timholy commented Oct 8, 2014

Updating #8501 to today's master yields the following new behavior: it fails on the first call, and succeeds thereafter. No segfault, either.

julia> function as_sub(x::AbstractMatrix)
           y = similar(x, eltype(x), tuple(([size(x)...]*2)...))
           @show typeof(y)
           y = sub(y, 2:2:size(y,1), 2:2:size(y,2))
           for j=1:size(x,2)
               for i=1:size(x,1)
                   y[i,j] = x[i,j]
               end
           end
           y
       end
as_sub (generic function with 1 method)

julia> as_sub(eye(2))
ERROR: `ndims` has no method matching ndims(::Type{Any})
 in ndims at abstractarray.jl:22 (repeats 3 times)
 in setindex! at subarray2.jl:34

julia> as_sub(eye(2))
typeof(y) = Array{Float64,2}
2x2 SubArray{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}:
 1.0  0.0
 0.0  1.0

julia> as_sub(eye(2))
typeof(y) = Array{Float64,2}
2x2 SubArray{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}:
 1.0  0.0
 0.0  1.0

@timholy
Copy link
Member Author

timholy commented Nov 8, 2014

I've finally gotten around to reducing this to a relatively simple test case that can be run on master.

module AVDebug

import Base: setindex!

type View{T,N,P<:AbstractArray,I<:(RangeIndex...)} <: AbstractArray{T,N}
    parent::P
    indexes::I
    dims::NTuple{N,Int}
end

stagedfunction subview(A::AbstractArray, I::RangeIndex...)
    T = eltype(A)
    N = length(I)
    @show T
    @show N
    @show A
    @show I
    :(AVDebug.View{$T,$N,$A,$I}(A, (I[1],I[2]), (length(I[1]), length(I[2]))))
end

stagedfunction setindex!{T,N,P}(A::View{T,N,P}, v, i1, i2)
    println("P = ", P)
    println("ndims = ", ndims(P))
    :(A.parent[2*i1,2*i2] = v)
end

end

with the test script:

function as_sub(x::AbstractMatrix)
    y = similar(x, eltype(x), tuple(([size(x)...]*2)...))
    @show typeof(y)
    Y = AVDebug.subview(y, 2:2:size(y,1), 2:2:size(y,2))
    @show typeof(Y)
    for j=1:size(x,2)
        for i=1:size(x,1)
            Y[i,j] = x[i,j]
        end
    end
    Y
end

as_sub(eye(2))

which yields the following output:

julia> include("views_broadcast_test.jl")
T = Any
N = 2
A = Array{Float64,N}
I = (StepRange{Int64,Int64},StepRange{Int64,Int64})
P = _<:AbstractArray{T,N}
T = Any
N = 2
A = Array{Float64,N}
I = (StepRange{Int64,Int64},StepRange{Int64,Int64})
P = _<:AbstractArray{T,N}
typeof(y) = Array{Float64,2}
typeof(Y) = View{Any,2,Array{Float64,N},(StepRange{Int64,Int64},StepRange{Int64,Int64})}
P = Array{Float64,N}
ERROR: `ndims` has no method matching ndims(::Type{Any})
 in ndims at abstractarray.jl:22 (repeats 3 times)
 in setindex! at /home/tim/tmp/views_broadcast.jl:23
 in as_sub at /home/tim/tmp/views_broadcast_test.jl:8
 in include at ./boot.jl:242
 in include_from_node1 at ./loading.jl:128
while loading /home/tim/tmp/views_broadcast_test.jl, in expression starting on line 14

Interestingly, if you change the subview function to the following:

stagedfunction subview{T,NP}(A::AbstractArray{T,NP}, I::RangeIndex...)
    N = length(I)
    @show T
    @show N
    @show A
    @show I
    :(AVDebug.View{$T,$N,$A,$I}(A, (I[1],I[2]), (length(I[1]), length(I[2]))))
end

then it works, with the following output:

julia> include("views_broadcast_test.jl")
T = Float64
N = 2
A = Array{Float64,N}
I = (StepRange{Int64,Int64},StepRange{Int64,Int64})
P = _<:AbstractArray{T,N}
T = Float64
N = 2
A = Array{Float64,N}
I = (StepRange{Int64,Int64},StepRange{Int64,Int64})
P = _<:AbstractArray{T,N}
typeof(y) = Array{Float64,2}
T = Float64
N = 2
A = Array{Float64,2}
I = (StepRange{Int64,Int64},StepRange{Int64,Int64})
typeof(Y) = View{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}
P = Array{Float64,2}
ndims = 2
Error showing value of type View{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})}:
ERROR: `size` has no method matching size(::View{Float64,2,Array{Float64,2},(StepRange{Int64,Int64},StepRange{Int64,Int64})})
 in showarray at show.jl:1097
 ...

(that final error is irrelevant, here I just didn't define a size method for Views)

Omitting the NP parameter from subview causes it to fail again.

@timholy
Copy link
Member Author

timholy commented Nov 8, 2014

Just to summarize what seems to be wrong:

  • subview can, in principle, be constructed in two circumstances: one in which the dimensionality of the "parent" array is unknown, and one in which it is known
  • without the type parameters, it never constructs the variant of subview for known dimensionality (notice in the first case that subview only runs twice)
  • adding the type parameters causes it to run the variant for known dimensionality (in the second case, subview runs 3 times)

So this seems to again be a case where method sorting is insufficiently picky; it's willing to tolerate a match to non-concrete types even once the types become concrete.

@timholy
Copy link
Member Author

timholy commented Nov 21, 2014

With the recent SubArray work, I was able to work around this by declaring parameters myfunction{T,N}(A::AbstractArray{T,N}, ...) to force recompilation once the dimensionality became known. But now I've found another case that I suspect is the same class of error.

With a recent julia-0.4 (one that includes the SubArray work), I've already committed a work-around for this problem to Images, but if one modifies these lines "back" to this:

function sliceim(img::AbstractImage, I::RangeIndex...)
    dimmap = Array(Int, ndims(img))
    n = 0
    for j = 1:ndims(img)
        if !isa(I[j], Int); n += 1; end;
        dimmap[j] = n
    end
    S = slice(img.data, I...)
    @show typeof(img.data)
    @show I
    @show typeof(S)
    ret = copyproperties(img, S) 

then one gets this

julia> using Images, TestImages
# unfixable (false) ambiguity warning suppressed

julia> img = separate(testimage("mandrill"))
RGB Image with:
  data: 512x512x3 Array{UfixedBase{UInt8,8},3}
  properties:
    IMcs: sRGB
    colorspace: RGB
    colordim: 3
    spatialorder:  y x
    pixelspacing:  1 1

julia> imgs = sliceim(img, 1:5, 1:5, 2)
typeof(img.data) = Array{UfixedBase{UInt8,8},3}
I = (1:5,1:5,2)
typeof(S) = SubArray{UfixedBase{UInt8,8},3,Array{UfixedBase{UInt8,8},3},(UnitRange{Int64},UnitRange{Int64},Int64,Int64...),1}
ERROR: `convert` has no method matching convert(::Type{SubArray{UfixedBase{UInt8,8},3,Array{UfixedBase{UInt8,8},3},(UnitRange{Int64},UnitRange{Int64},Int64,Int64...),1}}, ::SubArray{UfixedBase{UInt8,8},2,Array{UfixedBase{UInt8,8},3},(UnitRange{Int64},UnitRange{Int64},Int64),1})
 in call at no file
 in sliceim at /home/tim/.julia/v0.4/Images/src/core.jl:370

Note the very strange indexes type. The version I committed works around that by forcing specialization of sliceim for the tuple-type.

@timholy
Copy link
Member Author

timholy commented Nov 22, 2014

I know folks are busy and these stagedfunction/method sorting issues are not simple, so I may not get any responses to this post. But before getting started on implementing a candidate fix, I thought I'd sketch out an approach and see what people think. CC @Keno, @JeffBezanson.

Here are the ingredients:

Perhaps one approach to fix this is to change the isstaged field in a jl_methlist_t to stagedinfo: 0 means not staged, 1 means an instantiation from a stagedfunction, and 2 means an actual stagedfunction. We create new versions of cache_match and cache_match_by_type that require exact matches rather than subtype matching, and call these new versions when stagedinfo == 1.

Reasonable? I'm worried that there might be circumstances where it's reasonable to want subtype matching. Also, I don't understand the difference between cache_match and cache_match_by_type, and if any of the other match-related functions can bypass these. Any pointers would be greatly appreciated.

@timholy
Copy link
Member Author

timholy commented Dec 8, 2014

Jeff, since you're reading issues, care to comment on the strategy I proposed above? Basically the question is: for stagedfunction instantiations, is it reasonable to insist that they match only when the types align exactly? I might be able to implement this, but I'm not sure it's the right strategy.

@jakebolewski
Copy link
Member

By align exactly do you mean that the staged function argument types can only be concrete?

@timholy
Copy link
Member Author

timholy commented Dec 9, 2014

Probably a bad word choice. I just mean that the types match exactly (down to the parameters, etc).

@timholy
Copy link
Member Author

timholy commented Dec 9, 2014

(Non-concrete types can also match exactly, of course.)

timholy added a commit that referenced this issue Dec 29, 2014
@timholy timholy mentioned this issue Jan 1, 2015
4 tasks
@StefanKarpinski
Copy link
Member

cc @JeffBezanson, @Keno

@Jutho
Copy link
Contributor

Jutho commented Jan 8, 2015

Probably related, and also caused by max_tuple_length (or whatever it is called) equals 8:

stagedfunction g(a::Int...)
       N=length(a)
       :(NTuple{$N,Int})
 end

Directly

@code_typed g(1,1,1,1,1,1,1,1,1,1) # 10 arguments
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(a::(top(apply_type))(Vararg,Any)::Any::Any)], Any[Any[],Any[Any[:a,(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64),0]],Any[]], :(begin 
        return (Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)
    end::Type{(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)})))) # 10 Ints, correct

but then using this inside a function h()=g(1,1,1,1,1,1,1,1,1,1) results in

@code_typed h()
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[], Any[Any[:_var0],Any[Any[:_var0,(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64...),0]],Any[]], :(begin  # none, line 1:
        return (Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)
    end::Type{(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)})))) # Only 8 Ints

@timholy
Copy link
Member Author

timholy commented Jan 8, 2015

One dirty workaround I've found---though I haven't tested it for tuples of length 8 or higher---is that you can declare

g(a::Int...) = _g(a)
stagedfunction _g{TT}(a::TT)
    # blah blah
end

and that forces specialization for each tuple-type (TT). But this does required allocation of the tuple, so it's not nearly as good as if we just fixed this issue.

@Jutho
Copy link
Contributor

Jutho commented Jan 25, 2015

In response to the module AVDebug example above, I also noticed the strange behavior regarding inferring the value of T. This, however, seems to be solely related to how eltype is defined for AbstractArray. Note the following

eltype(AbstractArray{Float64}) #-> Any
eltype(AbstractArray{Float64,TypeVar(:N)}) #-> Any
eltype(AbstractArray{Float64,:N}) #-> Float64

So eltype returns the correct results as soon as there is a second type parameter, independent of whether it makes sense or not. I guess it wouldn't hurt to add a line
eltype{T}(::Type{AbstractArray{T}}) = T
to the existing
eltype{T,n}(::Type{AbstractArray{T,n}}) = T
in abstractarray.jl

@timholy
Copy link
Member Author

timholy commented Jan 25, 2015

I've been surprised by this before, too, so I'd agree that sounds like a reasonable addition.

@timholy
Copy link
Member Author

timholy commented Mar 5, 2015

Hooray!

@Jutho
Copy link
Contributor

Jutho commented Mar 5, 2015

+1. Was this the last of the remaining bugs with stagedfunctions? :-)

@StefanKarpinski
Copy link
Member

There's still the name bug.

@mauro3
Copy link
Contributor

mauro3 commented Mar 26, 2015

There is also #10178 left, and #9135 seems to be connected to that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior priority This should be addressed urgently
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants