# Function compiles twice but is called just once

**URL:** <https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536>\
**Category:** General Usage\
**Tags:** question, metaprogramming, compilation, type-stability\
**Created:** [April 29, 2025, 5:51pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536 "2025-04-29T17:51:46Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [April 29, 2025, 5:51pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536/1 "2025-04-29T17:51:46Z")

</div>

Consider the following code:

```julia-repl
julia> @generated function f(x)
           @info "Compiling f"
           return :(x + 1)
       end
f (generic function with 1 method)

julia> function type_unstable(y::Vector{Number})
           @info "Running type_unstable"
           x = 2 * y[1]
           return f(x)
       end
type_unstable (generic function with 1 method)

julia> type_unstable(Number[1.0])
[ Info: Compiling f # Wait, the call to `f` is a dynamic dispatch, why are we compiling `f` before knowing the type of `x`?
[ Info: Running type_unstable
[ Info: Compiling f
3.0

julia> using MethodAnalysis

julia> methodinstances(f)
2-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Any) # Why is this `MethodInstance` created?
 MethodInstance for f(::Float64)

```

In this code, `f` gets called once, but it gets compiled twice—once with an input of `Any` and once with an input of `Float64`.

Why does `f` get compiled twice, and why is one of those times before even knowing the type of the input?

Also, is there a way to modify this example so the dispatch is still dynamic but it only compiles once?

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [April 29, 2025, 6:59pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536/2 "2025-04-29T18:59:07Z")

</div>

Try this:

```julia
julia> @generated function f(x)
           x
           @info "Compiling f"
           return :(x + 1)
       end
f (generic function with 1 method)

julia> function type_unstable(y::Vector{Number})
           @info "Running type_unstable"
           x = 2 * y[1]
           return f(x)
       end
type_unstable (generic function with 1 method)

julia> type_unstable(Number[1.0])

```

It might have something to do with that `x` isn’t used in `f(x)`.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [April 29, 2025, 8:23pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536/3 "2025-04-29T20:23:30Z")

</div>

Thanks, that does help me have a cleaner example. But even with this I still see two method instances for `f`:

```julia-repl
julia> @generated function f(x)
           x
           @info "Compiling f"
           return :(x + 1)
       end
f (generic function with 1 method)

julia> function type_unstable(y::Vector{Number})
           @info "Running type_unstable"
           x = 2 * y[1]
           return f(x)
       end
type_unstable (generic function with 1 method)

julia> type_unstable(Number[1.0])
[ Info: Running type_unstable
[ Info: Compiling f # Good, only compiling once as expected.
3.0

julia> using MethodAnalysis

julia> methodinstances(f)
2-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Any) # Wait, why are there two `MethodInstance`s?
 MethodInstance for f(::Float64)

```

Even though `f` seemingly was compiled just once, there are still two `MethodInstance`s. Does the `f(::Any)` method instance have to do with the fact that `f` is a `@generated` function?

Maybe I need to update my mental model of `@generated` functions as follows: A `@generated` function is really two functions: one that creates the code that runs, and another that runs the generated code. That would explain why there are two method instances, the `::Any` instance being the method that creates the generated code. Is this mental model correct?

But why is there only one `Compiling f` info statement that prints in this version of `f`?

---

<div class="post-metadata">

**Author:** ![Uve](https://avatars.discourse-cdn.com/v4/letter/u/82dd89/32.png) [@Uve](https://discourse.julialang.org/u/Uve)\
**Post date:** [April 29, 2025, 9:45pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536/4 "2025-04-29T21:45:05Z")

</div>

Don’t take my comments for granted because these compiler topics are beyond my understanding, but I will try to comment on some of the details I have noticed.

> Even though f seemingly was compiled just once, there are still two MethodInstances. Does the f(::Any) method instance have to do with the fact that f is a @generated function?

About the number of instances, I would say it has to do with the fact that `Number` is not a concrete type and not with the fact that it is a generated function.

```julia
julia> isconcretetype(Number)
false

```

I say this because if you define the `type_unstable` function without any type annotation and you run the function for concrete types, no `f(::Any)` function is generated.

```julia
julia> @generated function f(x)
           @info "Compiling f"
           return :(x + 1)
       end
f (generic function with 1 method)

julia> function type_unstable(y)
           @info "Running type_unstable"
           x = 2 * y[1]
           return f(x)
       end
type_unstable (generic function with 1 method)

julia> using MethodAnalysis

julia> type_unstable([1.0])
[ Info: Compiling f
[ Info: Running type_unstable
3.0

julia> methodinstances(f)
1-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Float64)

julia> type_unstable([1])
[ Info: Compiling f
[ Info: Running type_unstable
3

julia> methodinstances(f)
2-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Float64)
 MethodInstance for f(::Int64)

julia> type_unstable([ComplexF32(1.0)])
[ Info: Compiling f
[ Info: Running type_unstable
3.0f0 + 0.0f0im

julia> methodinstances(f)
3-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Float64)
 MethodInstance for f(::Int64)
 MethodInstance for f(::ComplexF32)

julia> type_unstable(Number[1.0])
[ Info: Compiling f
[ Info: Running type_unstable
3.0

julia> type_unstable(Number[1.0])
methodinstances(f)
4-element Vector{Core.MethodInstance}:
 MethodInstance for f(::Float64)
 MethodInstance for f(::Int64)
 MethodInstance for f(::ComplexF32)
 MethodInstance for f(::Any)

```

> But why is there only one Compiling f info statement that prints in this version of f?

It may (or may not) have something to do with something mentioned in the manual. From [https://docs.julialang.org/en/v1/manual/metaprogramming/:](https://docs.julialang.org/en/v1/manual/metaprogramming/:)

> The number of times a generated function is generated might be only once, but it might also be more often, or appear to not happen at all. As a consequence, you should never write a generated function with side effects - when, and how often, the side effects occur is undefined…

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [April 29, 2025, 10:09pm UTC](https://discourse.julialang.org/t/function-compiles-twice-but-is-called-just-once/128536/5 "2025-04-29T22:09:48Z")

</div>

> [@Uve](#):
>
> I say this because if you define the `type_unstable` function without any type annotation and you run the function for concrete types, no `f(::Any)` function is generated.

Interesting, I hadn’t noticed that.

And thanks for reminding me about the docs, it had been a while since I read the [section on generated functions](https://docs.julialang.org/en/v1/manual/metaprogramming/#Generated-functions), and that satisfactorily answered my questions.
