<p dir="auto">Over at <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="133037270" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/15030" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/15030/hovercard" href="https://github.com/JuliaLang/julia/pull/15030">#15030</a>, I'm trying to rewrite <code class="notranslate">ntuple(f, Val{N})</code> so that we don't need <code class="notranslate">@generated</code> functions. It's not yet viable because, for this particular problem, codegen quality is poor. I think I've narrowed it down to a failure to substitute integer-valued <code class="notranslate">GenSym</code>s during codegen. Here's a lispy rewrite of that code that produces very simple lowered &amp; typed code:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="using Base: @_inline_meta

# The &quot;reference implementation&quot;
myntuple1(f, ::Type{Val{3}}) = (f(1), f(2), f(3))

# The implementation I want
function myntuple2{N}(f, ::Type{Val{N}})
    @_inline_meta   # this doesn't seem to affect anything
    _ntuple((), f, Val{N})
end

# Build up the output until it has length N
_ntuple{N}(out::NTuple{N}, f, ::Type{Val{N}}) = out
function _ntuple{N}(out, f, ::Type{Val{N}})
    @_inline_meta
    _ntuple(out, (out..., 0), f, Val{N})  # compile-time evaluation of length(out)+1
end
function _ntuple{N,M}(out, ::NTuple{M}, f, ::Type{Val{N}})
    @_inline_meta
    _ntuple((out..., f(M)), f, Val{N})
end"><pre class="notranslate"><span class="pl-k">using</span> Base<span class="pl-k">:</span> <span class="pl-c1">@_inline_meta</span>

<span class="pl-c"><span class="pl-c">#</span> The "reference implementation"</span>
<span class="pl-en">myntuple1</span>(f, <span class="pl-k">::</span><span class="pl-c1">Type{Val{3}}</span>) <span class="pl-k">=</span> (<span class="pl-c1">f</span>(<span class="pl-c1">1</span>), <span class="pl-c1">f</span>(<span class="pl-c1">2</span>), <span class="pl-c1">f</span>(<span class="pl-c1">3</span>))

<span class="pl-c"><span class="pl-c">#</span> The implementation I want</span>
<span class="pl-k">function</span> <span class="pl-en">myntuple2</span><span class="pl-c1">{N}</span>(f, <span class="pl-k">::</span><span class="pl-c1">Type{Val{N}}</span>)
    <span class="pl-c1">@_inline_meta</span>   <span class="pl-c"><span class="pl-c">#</span> this doesn't seem to affect anything</span>
    <span class="pl-c1">_ntuple</span>((), f, Val{N})
<span class="pl-k">end</span>

<span class="pl-c"><span class="pl-c">#</span> Build up the output until it has length N</span>
<span class="pl-en">_ntuple</span><span class="pl-c1">{N}</span>(out<span class="pl-k">::</span><span class="pl-c1">NTuple{N}</span>, f, <span class="pl-k">::</span><span class="pl-c1">Type{Val{N}}</span>) <span class="pl-k">=</span> out
<span class="pl-k">function</span> <span class="pl-en">_ntuple</span><span class="pl-c1">{N}</span>(out, f, <span class="pl-k">::</span><span class="pl-c1">Type{Val{N}}</span>)
    <span class="pl-c1">@_inline_meta</span>
    <span class="pl-c1">_ntuple</span>(out, (out<span class="pl-k">...</span>, <span class="pl-c1">0</span>), f, Val{N})  <span class="pl-c"><span class="pl-c">#</span> compile-time evaluation of length(out)+1</span>
<span class="pl-k">end</span>
<span class="pl-k">function</span> <span class="pl-en">_ntuple</span><span class="pl-c1">{N,M}</span>(out, <span class="pl-k">::</span><span class="pl-c1">NTuple{M}</span>, f, <span class="pl-k">::</span><span class="pl-c1">Type{Val{N}}</span>)
    <span class="pl-c1">@_inline_meta</span>
    <span class="pl-c1">_ntuple</span>((out<span class="pl-k">...</span>, <span class="pl-c1">f</span>(M)), f, Val{N})
<span class="pl-k">end</span></pre></div>
<p dir="auto">Results:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; @code_typed myntuple1(identity, Val{3})
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[symbol(&quot;#self#&quot;),:f,symbol(&quot;#unused#&quot;)], Any[Any[Any[symbol(&quot;#self#&quot;),#myntuple1,0],Any[:f,Base.#identity,64]],Any[],Any[]], :(begin  # /tmp/ntuple2.jl, line 4:
        return (top(tuple))(1,2,3)::Tuple{Int64,Int64,Int64}
    end::Tuple{Int64,Int64,Int64}))))

julia&gt; @code_typed myntuple2(identity, Val{3})
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[symbol(&quot;#self#&quot;),:f,symbol(&quot;#unused#&quot;)], Any[Any[Any[symbol(&quot;#self#&quot;),#myntuple2,0],Any[:f,Base.#identity,0]],Any[],Any[Tuple{Int64,Int64},Int64,Int64]], :(begin  # /tmp/ntuple2.jl, line 8:
        $(Expr(:meta, :inline)) # /tmp/ntuple2.jl, line 9: # /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19: # /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19:
        GenSym(1) = 1
        GenSym(2) = 2 # /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19:
        return (top(tuple))(GenSym(1),GenSym(2),3)::Tuple{Int64,Int64,Int64}
    end::Tuple{Int64,Int64,Int64}))))

julia&gt; @code_native myntuple1(identity, Val{3})
        .text
Filename: ntuple2.jl
Source line: 0
        pushq   %rbp
        movq    %rsp, %rbp
Source line: 4
        movq    $3, 16(%rdi)
        movq    $2, 8(%rdi)
        movq    $1, (%rdi)
        movq    %rdi, %rax
        popq    %rbp
        retq

julia&gt; @code_native myntuple2(identity, Val{3})
        .text
Filename: ntuple2.jl
Source line: 0
        pushq   %rbp
        movq    %rsp, %rbp
        pushq   %r15
        pushq   %r14
        pushq   %r13
        pushq   %r12
        pushq   %rbx
        subq    $104, %rsp
        movq    %rdi, %rbx
        leaq    -56(%rbp), %r12
        leaq    -88(%rbp), %rdi
        movq    $0, -120(%rbp)
        movq    $0, -112(%rbp)
        movq    $0, -104(%rbp)
        movq    $0, -96(%rbp)
        movq    $0, -72(%rbp)
        movq    $0, -64(%rbp)
        movq    $0, -56(%rbp)
        movq    $0, -48(%rbp)
        movq    $20, -136(%rbp)
        movabsq $jl_tls_states, %r13
        movq    (%r13), %rax
        movq    %rax, -128(%rbp)
        leaq    -136(%rbp), %rax
        movq    %rax, (%r13)
Source line: 19
        movq    %rbx, -88(%rbp)
        movabsq $140407980499072, %r14  # imm = 0x7FB347CD2080
        movq    %r14, -80(%rbp)
        movabsq $jl_apply_generic, %r15
        movl    $2, %esi
        callq   *%r15
        movq    %rax, -112(%rbp)
        movq    %rbx, -56(%rbp)
        leaq    48(%r14), %rax
        movq    %rax, -48(%rbp)
        movl    $2, %esi
        movq    %r12, %rdi
        callq   *%r15
        movq    %rax, -104(%rbp)
        movq    %rbx, -72(%rbp)
        orq     $96, %r14
        movq    %r14, -64(%rbp)
        movl    $2, %esi
        leaq    -72(%rbp), %rdi
        callq   *%r15
        movq    %rax, -96(%rbp)
        movabsq $jl_f_tuple, %rax
        xorl    %edi, %edi
        movl    $3, %edx
        leaq    -112(%rbp), %rsi
        callq   *%rax
        movq    %rax, -120(%rbp)
Source line: 12
        movq    -128(%rbp), %rcx
        movq    %rcx, (%r13)
        addq    $104, %rsp
        popq    %rbx
        popq    %r12
        popq    %r13
        popq    %r14
        popq    %r15
        popq    %rbp
        retq"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_typed</span> <span class="pl-c1">myntuple1</span>(identity, Val{<span class="pl-c1">3</span>})
<span class="pl-c1">1</span><span class="pl-k">-</span>element Array{Any,<span class="pl-c1">1</span>}<span class="pl-k">:</span>
 :(<span class="pl-k">$</span>(<span class="pl-c1">Expr</span>(<span class="pl-c1">:lambda</span>, Any[<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#self#<span class="pl-pds">"</span></span>),<span class="pl-c1">:f</span>,<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#unused#<span class="pl-pds">"</span></span>)], Any[Any[Any[<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#self#<span class="pl-pds">"</span></span>),<span class="pl-c"><span class="pl-c">#</span>myntuple1,0],Any[:f,Base.#identity,64]],Any[],Any[]], :(begin  # /tmp/ntuple2.jl, line 4:</span>
        <span class="pl-k">return</span> (<span class="pl-c1">top</span>(tuple))(<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>)<span class="pl-k">::</span><span class="pl-c1">Tuple{Int64,Int64,Int64}</span>
    <span class="pl-c1">end</span><span class="pl-k">::</span><span class="pl-c1">Tuple{Int64,Int64,Int64}</span>))))

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_typed</span> <span class="pl-c1">myntuple2</span>(identity, Val{<span class="pl-c1">3</span>})
<span class="pl-c1">1</span><span class="pl-k">-</span>element Array{Any,<span class="pl-c1">1</span>}<span class="pl-k">:</span>
 :(<span class="pl-k">$</span>(<span class="pl-c1">Expr</span>(<span class="pl-c1">:lambda</span>, Any[<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#self#<span class="pl-pds">"</span></span>),<span class="pl-c1">:f</span>,<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#unused#<span class="pl-pds">"</span></span>)], Any[Any[Any[<span class="pl-c1">symbol</span>(<span class="pl-s"><span class="pl-pds">"</span>#self#<span class="pl-pds">"</span></span>),<span class="pl-c"><span class="pl-c">#</span>myntuple2,0],Any[:f,Base.#identity,0]],Any[],Any[Tuple{Int64,Int64},Int64,Int64]], :(begin  # /tmp/ntuple2.jl, line 8:</span>
        <span class="pl-k">$</span>(<span class="pl-c1">Expr</span>(<span class="pl-c1">:meta</span>, <span class="pl-c1">:inline</span>)) <span class="pl-c"><span class="pl-c">#</span> /tmp/ntuple2.jl, line 9: # /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19: # /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19:</span>
        <span class="pl-en">GenSym</span>(<span class="pl-c1">1</span>) <span class="pl-k">=</span> <span class="pl-c1">1</span>
        <span class="pl-en">GenSym</span>(<span class="pl-c1">2</span>) <span class="pl-k">=</span> <span class="pl-c1">2</span> <span class="pl-c"><span class="pl-c">#</span> /tmp/ntuple2.jl, line 14: # /tmp/ntuple2.jl, line 15: # /tmp/ntuple2.jl, line 18: # /tmp/ntuple2.jl, line 19:</span>
        <span class="pl-k">return</span> (<span class="pl-c1">top</span>(tuple))(<span class="pl-c1">GenSym</span>(<span class="pl-c1">1</span>),<span class="pl-c1">GenSym</span>(<span class="pl-c1">2</span>),<span class="pl-c1">3</span>)<span class="pl-k">::</span><span class="pl-c1">Tuple{Int64,Int64,Int64}</span>
    <span class="pl-c1">end</span><span class="pl-k">::</span><span class="pl-c1">Tuple{Int64,Int64,Int64}</span>))))

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_native</span> <span class="pl-c1">myntuple1</span>(identity, Val{<span class="pl-c1">3</span>})
        <span class="pl-k">.</span>text
Filename<span class="pl-k">:</span> ntuple2<span class="pl-k">.</span>jl
Source line<span class="pl-k">:</span> <span class="pl-c1">0</span>
        pushq   <span class="pl-k">%</span>rbp
        movq    <span class="pl-k">%</span>rsp, <span class="pl-k">%</span>rbp
Source line<span class="pl-k">:</span> <span class="pl-c1">4</span>
        movq    <span class="pl-k">$</span>3, <span class="pl-c1">16</span>(<span class="pl-k">%</span>rdi)
        movq    <span class="pl-k">$</span>2, <span class="pl-c1">8</span>(<span class="pl-k">%</span>rdi)
        movq    <span class="pl-k">$</span>1, (<span class="pl-k">%</span>rdi)
        movq    <span class="pl-k">%</span>rdi, <span class="pl-k">%</span>rax
        popq    <span class="pl-k">%</span>rbp
        retq

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_native</span> <span class="pl-c1">myntuple2</span>(identity, Val{<span class="pl-c1">3</span>})
        <span class="pl-k">.</span>text
Filename<span class="pl-k">:</span> ntuple2<span class="pl-k">.</span>jl
Source line<span class="pl-k">:</span> <span class="pl-c1">0</span>
        pushq   <span class="pl-k">%</span>rbp
        movq    <span class="pl-k">%</span>rsp, <span class="pl-k">%</span>rbp
        pushq   <span class="pl-k">%</span>r15
        pushq   <span class="pl-k">%</span>r14
        pushq   <span class="pl-k">%</span>r13
        pushq   <span class="pl-k">%</span>r12
        pushq   <span class="pl-k">%</span>rbx
        subq    <span class="pl-k">$</span>104, <span class="pl-k">%</span>rsp
        movq    <span class="pl-k">%</span>rdi, <span class="pl-k">%</span>rbx
        leaq    <span class="pl-k">-</span><span class="pl-c1">56</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>r12
        leaq    <span class="pl-k">-</span><span class="pl-c1">88</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>rdi
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">120</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">112</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">104</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">96</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">72</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">64</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">56</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>0, <span class="pl-k">-</span><span class="pl-c1">48</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">$</span>20, <span class="pl-k">-</span><span class="pl-c1">136</span>(<span class="pl-k">%</span>rbp)
        movabsq <span class="pl-k">$</span>jl_tls_states, <span class="pl-k">%</span>r13
        movq    (<span class="pl-k">%</span>r13), <span class="pl-k">%</span>rax
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">128</span>(<span class="pl-k">%</span>rbp)
        leaq    <span class="pl-k">-</span><span class="pl-c1">136</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>rax
        movq    <span class="pl-k">%</span>rax, (<span class="pl-k">%</span>r13)
Source line<span class="pl-k">:</span> <span class="pl-c1">19</span>
        movq    <span class="pl-k">%</span>rbx, <span class="pl-k">-</span><span class="pl-c1">88</span>(<span class="pl-k">%</span>rbp)
        movabsq <span class="pl-k">$</span>140407980499072, <span class="pl-k">%</span>r14  <span class="pl-c"><span class="pl-c">#</span> imm = 0x7FB347CD2080</span>
        movq    <span class="pl-k">%</span>r14, <span class="pl-k">-</span><span class="pl-c1">80</span>(<span class="pl-k">%</span>rbp)
        movabsq <span class="pl-k">$</span>jl_apply_generic, <span class="pl-k">%</span>r15
        movl    <span class="pl-k">$</span>2, <span class="pl-k">%</span>esi
        callq   <span class="pl-k">*%</span>r15
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">112</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">%</span>rbx, <span class="pl-k">-</span><span class="pl-c1">56</span>(<span class="pl-k">%</span>rbp)
        leaq    <span class="pl-c1">48</span>(<span class="pl-k">%</span>r14), <span class="pl-k">%</span>rax
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">48</span>(<span class="pl-k">%</span>rbp)
        movl    <span class="pl-k">$</span>2, <span class="pl-k">%</span>esi
        movq    <span class="pl-k">%</span>r12, <span class="pl-k">%</span>rdi
        callq   <span class="pl-k">*%</span>r15
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">104</span>(<span class="pl-k">%</span>rbp)
        movq    <span class="pl-k">%</span>rbx, <span class="pl-k">-</span><span class="pl-c1">72</span>(<span class="pl-k">%</span>rbp)
        orq     <span class="pl-k">$</span>96, <span class="pl-k">%</span>r14
        movq    <span class="pl-k">%</span>r14, <span class="pl-k">-</span><span class="pl-c1">64</span>(<span class="pl-k">%</span>rbp)
        movl    <span class="pl-k">$</span>2, <span class="pl-k">%</span>esi
        leaq    <span class="pl-k">-</span><span class="pl-c1">72</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>rdi
        callq   <span class="pl-k">*%</span>r15
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">96</span>(<span class="pl-k">%</span>rbp)
        movabsq <span class="pl-k">$</span>jl_f_tuple, <span class="pl-k">%</span>rax
        xorl    <span class="pl-k">%</span>edi, <span class="pl-k">%</span>edi
        movl    <span class="pl-k">$</span>3, <span class="pl-k">%</span>edx
        leaq    <span class="pl-k">-</span><span class="pl-c1">112</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>rsi
        callq   <span class="pl-k">*%</span>rax
        movq    <span class="pl-k">%</span>rax, <span class="pl-k">-</span><span class="pl-c1">120</span>(<span class="pl-k">%</span>rbp)
Source line<span class="pl-k">:</span> <span class="pl-c1">12</span>
        movq    <span class="pl-k">-</span><span class="pl-c1">128</span>(<span class="pl-k">%</span>rbp), <span class="pl-k">%</span>rcx
        movq    <span class="pl-k">%</span>rcx, (<span class="pl-k">%</span>r13)
        addq    <span class="pl-k">$</span>104, <span class="pl-k">%</span>rsp
        popq    <span class="pl-k">%</span>rbx
        popq    <span class="pl-k">%</span>r12
        popq    <span class="pl-k">%</span>r13
        popq    <span class="pl-k">%</span>r14
        popq    <span class="pl-k">%</span>r15
        popq    <span class="pl-k">%</span>rbp
        retq</pre></div>
<p dir="auto">Is there any chance this has an easy fix? Like, add a "substitute constant-valued GenSyms" pass during codegen?</p>
<p dir="auto">In <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="70459793" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/10961" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/10961/hovercard" href="https://github.com/JuliaLang/julia/pull/10961">#10961</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/swt30/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/swt30">@swt30</a> found and fixed a performance problem with <code class="notranslate">collect</code>.  It was type-unstable because it had been defined as <code class="notranslate">collect(T::Type, itr)</code> instead of <code class="notranslate">collect{T}(::Type{T}, itr)</code>.  But <code class="notranslate">@code_warntype</code> gave it a pass:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; @code_warntype collect([1,2,3])
Variables:
  itr::Array{Int64,1}

Body:
  begin  # array.jl, line 273:
      return collect(Int64,itr::Array{Int64,1})::Array{Int64,1}
  end::Array{Int64,1}

julia&gt; @code_warntype collect(Int, [1,2,3])
  T::Type{Int64}
  itr::Array{Int64,1}
  i::Int64
  a::Array{Int64,1}
… # Long, but no red flags"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_warntype</span> <span class="pl-c1">collect</span>([<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>])
Variables<span class="pl-k">:</span>
  itr<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>

Body<span class="pl-k">:</span>
  <span class="pl-k">begin</span>  <span class="pl-c"><span class="pl-c">#</span> array.jl, line 273:</span>
      <span class="pl-k">return</span> <span class="pl-c1">collect</span>(Int64,itr<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>)<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>
  <span class="pl-k">end</span><span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">@code_warntype</span> <span class="pl-c1">collect</span>(Int, [<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>])
  T<span class="pl-k">::</span><span class="pl-c1">Type{Int64}</span>
  itr<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>
  i<span class="pl-k">::</span><span class="pl-c1">Int64</span>
  a<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>
… <span class="pl-c"><span class="pl-c">#</span> Long, but no red flags</span></pre></div>
<p dir="auto">It's particularly tricky in this case because inference gets it right <em>outside</em> the function, and then when you look inside with <code class="notranslate">@code_warntype</code> the macro automatically considers the type of its type arguments to be <code class="notranslate">Type{T}</code> and not <code class="notranslate">DataType</code>.  Often this is what you want (in fact, I did this in one of my first PRs), but it isn't correct in this case.</p>
<p dir="auto">This is what we should have seen:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; code_warntype(collect, Tuple{DataType, Array{Int,1}})
Variables:
  T::DataType
  itr::Array{Int64,1}
  i::Int64
  a::Array{T,N}
..."><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">code_warntype</span>(collect, Tuple{DataType, Array{Int,<span class="pl-c1">1</span>}})
Variables<span class="pl-k">:</span>
  T<span class="pl-k">::</span><span class="pl-c1">DataType</span>
  itr<span class="pl-k">::</span><span class="pl-c1">Array{Int64,1}</span>
  i<span class="pl-k">::</span><span class="pl-c1">Int64</span>
  a<span class="pl-k">::</span><span class="pl-c1">Array{T,N}</span>
<span class="pl-k">...</span></pre></div>
<p dir="auto">I'm not sure how to fix this — we want the <code class="notranslate">Type{T}</code> definition while looking up the method, but then we don't want to pass inference more information than it'll normally get when running the code.</p>