# Tell the compiler the return type of function chosen at runtime

**URL:** <https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429>\
**Category:** Performance\
**Tags:** question, code\_warntype, type-stability\
**Created:** [August 20, 2024, 7:57pm UTC](https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429 "2024-08-20T19:57:13Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ljg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ljg/32/52366_2.png) [@ljg](https://discourse.julialang.org/u/ljg)\
**Post date:** [August 20, 2024, 7:57pm UTC](https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429/1 "2024-08-20T19:57:13Z")

</div>

The following MRE function:

```julia
function fun(idx, a::Int, b::Int)
    funs = [+, -]
    return funs[idx](a, b)
end

```

Is not type-stable because Julia does not infer the return type of `funs[idx]`. Here is the output of `@code_warntype fun(1, 2, 3)`:

```julia
MethodInstance for fun(::Int64, ::Int64, ::Int64)
  from fun(idx, a, b) @ Main 
Arguments
  #self#::Core.Const(fun)
  idx::Int64
  a::Int64
  b::Int64
Locals
  funs::Vector{Function}
Body::Any
1 ─ (funs = Base.vect(Main.:+, Main.:-))
│ %2 = Base.getindex(funs, idx)::Function
│ %3 = (%2)(a, b)::Any
└── return %3

```

Say that I know the return type will always be `Int64`. Is there an annotation, or parametric type for `funs` that will tell the compiler that? Is there another way to help the compiler infer the return type in similar cases?

---

<div class="post-metadata">

**Author:** ![JonasWickman](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@JonasWickman](https://discourse.julialang.org/u/JonasWickman)\
**Post date:** [August 20, 2024, 8:13pm UTC](https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429/2 "2024-08-20T20:13:13Z")

</div>

You can use FunctionWrappers.jl:

```julia
import FunctionWrappers: FunctionWrapper

function fun(idx, a::Int, b::Int)
    funs = FunctionWrapper{Int64, Tuple{Int64, Int64}}[+, -]
    return funs[idx](a, b)
end

@code_warntype fun(1, 3, 5)

```

Not a lot of documentation available, but I think it’s used quite extensively across the Julia ecosystem. Hopefully someone else can fill any technical details.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [August 21, 2024, 4:28am UTC](https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429/3 "2024-08-21T04:28:32Z")

</div>

If you only have 2 or 3 functions, replacing the vector with a tuple also does the trick:

```julia
function fun(idx, a::Int, b::Int)
    funs = (+, -)
    return funs[idx](a, b)
end

```

```julia-repl
julia> @code_warntype fun(1, 2, 3)
MethodInstance for fun(::Int64, ::Int64, ::Int64)
  from fun(idx, a::Int64, b::Int64) @ Main REPL[1]:1
Arguments
  #self#::Core.Const(fun)
  idx::Int64
  a::Int64
  b::Int64
Locals
  funs::Tuple{typeof(+), typeof(-)}
Body::Int64
1 ─ (funs = Core.tuple(Main.:+, Main.:-))
│ %2 = Base.getindex(funs, idx)::Union{typeof(+), typeof(-)}
│ %3 = (%2)(a, b)::Int64
└── return %3

```

---

<div class="post-metadata">

**Author:** ![jakobjpeters](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobjpeters/32/207797_2.png) [@jakobjpeters](https://discourse.julialang.org/u/jakobjpeters)\
**Post date:** [August 21, 2024, 7:10am UTC](https://discourse.julialang.org/t/tell-the-compiler-the-return-type-of-function-chosen-at-runtime/118429/4 "2024-08-21T07:10:52Z")

</div>

Another simple option is to use type annotations, but note that the annotation needs to be both concrete and determined at compile time.

```julia
funs[idx](a, b)::Int

```

```julia
1 ─ (funs = Base.vect(Main.:+, Main.:-))
│ %2 = Base.getindex(funs, idx)::Function
│ %3 = (%2)(a, b)::Any
│ %4 = Core.typeassert(%3, Main.Int)::Int64
└── return %4

```
