# A bug in tuple type-inferencing, or a subtlety?

**URL:** <https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806>\
**Category:** General Usage\
**Created:** [September 10, 2017, 4:47am UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806 "2017-09-10T04:47:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [September 10, 2017, 4:47am UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806/1 "2017-09-10T04:47:54Z")

</div>

In the code below, `test_inf2` does not work (see the error message that follows), and yet `test_inf1` and `test_inf3` are fine. Is this a bug in the type-inference system? Note that for my actual code, the solution presented by `test_inf3` is suitable, but the manual specifically states that users should prefer the technique of `test_inf2` over that of `test_inf3`.

```julia
module test_valtype

function test_inf1()
    test_inf1_(Val{3})
end

function test_inf1_(::Type{Val{N}}) where N
    println("N = ", N)
    nothing
end

function test_inf2()
    test_inf2_((2, Val{3}))
end

function test_inf2_(::Tuple{Int, Type{Val{N}}}) where N
    println("N = ", N)
    nothing
end

function test_inf3()
    test_inf3_((2, Val{3}()))
end

function test_inf3_(::Tuple{Int, Val{N}}) where N
    println("N = ", N)
    nothing
end

end

```

Here is the error:

```julia
julia> test_valtype.test_inf1()
N = 3

julia> test_valtype.test_inf2()
ERROR: MethodError: no method matching test_inf2_(::Tuple{Int64,DataType})
Closest candidates are:
  test_inf2_(::Tuple{Int64,Type{Val{N}}}) where N at C:\Users\vavasis\ownCloud\Documents\Katerina\cohesive\conic_jl\test_valtype.jl:17
Stacktrace:
 [1] test_inf2() at C:\Users\vavasis\ownCloud\Documents\Katerina\cohesive\conic_jl\test_valtype.jl:13

julia> test_valtype.test_inf3()
N = 3

```

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [September 10, 2017, 12:10pm UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806/2 "2017-09-10T12:10:48Z")

</div>

> <https://github.com/JuliaLang/julia/issues/10947>
>
> This may be intentional, but I found it surprising.
> 
> \`\`\`
> \_
> \_ … \_ \_(\_)\_ | A fresh approach to technical computing
> (\_) | (\_) (\_) | Documentation: http://docs.julialang.org
> \_ \_ \_| |\_ \_\_ \_ | Type "help()" for help.
> | | | | | | |/ \_\` | |
> | | |\_| | | | (\_| | | Version 0.4.0-dev+4452 (2015-04-22 15:05 UTC)
> \_/ |\\\_\_'\_|\_|\_|\\\_\_'\_| | Commit 19b2dd5\* (0 days old master)
> |\_\_/ | x86\_64-apple-darwin14.3.0
> 
> julia\> type A end
> 
> julia\> isa(A, Type{A})
> true
> 
> julia\> isa((A,), Tuple{Type{A}})
> false
> 
> julia\> isa(convert(Tuple{Type{A}}, (A,)), Tuple{Type{A}})
> false
> \`\`\`
> 
> Whereas in 0.3
> 
> \`\`\`
> julia\> type A end
> 
> julia\> isa(A, Type{A})
> true
> 
> julia\> isa((A,), (Type{A},))
> true
> \`\`\`
> 
> This is in the context of https://github.com/JuliaStats/KernelDensity.jl/pull/14. @sebastiang is trying to dispatch on something that boils down to \`foo{T \<: A, T \<: A}(::Tuple{Type{T}, Type{T}})\` but can't figure out how to make in work, nor can I. Am I wrong in expecting it to work?

> [@Stephen\_Vavasis](#):
>
> the manual specifically states that users should prefer the technique of test\_inf2 over that of test\_inf3.

FWIW, as someone who benchmarked performance-sensitive tuples a lot, I would recommend the opposite. But I’d love to know what the manual’s justification is. For one, `Val{N}` is `isbits` but `Type{Val{N}}` isn’t.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [September 10, 2017, 2:29pm UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806/3 "2017-09-10T14:29:23Z")

</div>

The recommendation was changed to use `Val{N}` instead of `Type{Val{N}`

> <https://github.com/JuliaLang/julia/pull/22475>
>
> @JeffBezanson as discussed. Instead of calling \`f(Val{x})\` and method definition…s \`f(::Type{Val{x}}) where x = ...\`, we use \`f(Val(x))\` and \`f(::Val{x}) where x = ...\`. There is a new \`@pure\` function for \`Val(x) -\> Val{x}()\`, a \`show\` override, and a docstring/doctest.
> 
> ~~This is WIP and so far only "upgrades" two functions (\`ntuple\` and \`fill\_to\_length\`). I am currently intending to replace~~ I have replaced all uses of \`Val{x}\` in \`Base\` with the new constructor (except for specific inference tests targeting type parameters).
> 
> Also, what does this mean when building? I'm kind-of lost with the documentation system.
> 
> \> WARNING: replacing docs for 'Base.Val :: Union{}' in module 'Base'.

> For consistency across Julia, the call site should always pass a Val instance rather than using a type, i.e., use foo(Val(:bar)) rather than foo(Val{:bar}).

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [September 10, 2017, 9:05pm UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806/4 "2017-09-10T21:05:54Z")

</div>

Thanks for the prompt responses and clarifications! One last question: the reason that my code is structured as in the above snippet is that I want a performant “function barrier” between `test_inf1` and `test_inf1_`. In particular, the number `3` that appears in `test_inf1` could be an arbitrary `Int` program variable, but when it reaches `test_inf1_`, it is now a compile-time constant that can lead to loop-unrolling or other code optimizations. The same holds for `test_inf3`. Will it work the way that I imagine? Is this a standard “Julian” idiom?

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [September 10, 2017, 11:32pm UTC](https://discourse.julialang.org/t/a-bug-in-tuple-type-inferencing-or-a-subtlety/5806/5 "2017-09-10T23:32:12Z")

</div>

> [@Stephen\_Vavasis](#):
>
> Will it work the way that I imagine?

I believe that `ntuple` will always unroll, but every other construct is governed by the compiler’s optimization heuristics. I wrote [Unrolled.jl](https://github.com/cstjean/Unrolled.jl#unrolled-functions) to get more control over the process.
