# How @code\_warntype , precompilation, execution and type interference works?

**URL:** <https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674>\
**Category:** New to Julia\
**Tags:** precompilation, code\_warntype\
**Created:** [January 20, 2021, 3:49pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674 "2021-01-20T15:49:14Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 20, 2021, 3:49pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/1 "2021-01-20T15:49:14Z")

</div>

Hey Julianners,

I found a really strange behavior! But shit is pretty serious thing all in all.

```julia
using InteractiveUtils
struct me{I,O}
	a::Vector{Array{Float32,I}}
	b::Vector{Array{Float32,O}}
end

double(x::Vector{Array{Float32, 3}}) = 2 .* x

function foo(n) 
	double(n.a)
end

function bar()
	m=me{3,2}([randn(Float32,2,3,4)],[randn(Float32,2,4)])
	foo(m)
end
@code_warntype bar()

```

So bar is an uninterferable thing… which is strange… But ok.  
Then running this code snippet:

```julia
@time bar();
@code_warntype bar()
double(x::Vector{Array{Float32, 3}}) = 2 .* x
@code_warntype bar()

```

After redefining double(…), bar() becomes an interferable class!! 🤨

What is going on here?

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 20, 2021, 5:19pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/2 "2021-01-20T17:19:30Z")

</div>

I don’t know if I was using it right… but I think I found the error with SnoopCompile.jl

Replacing double to 2 to 2.f0:  
`double(x::Vector{Array{Float32, 3}}) = 2.f0 .* x`  
So the problem maybe was with: \*(::Int64, ::Array{Float32, 3})

Interesting anyway.  
If someone else know the problem came from something different then let me know.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 20, 2021, 5:31pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/3 "2021-01-20T17:31:57Z")

</div>

I think that the problem is more related with the parameterization of the `me` struct. If you define it with:

```julia
julia> struct me{I,O}
               a::I
               b::O
       end

```

Everything becomes type-stable. I do not have the full expertise to explain this, but I think that to use the sizes of the arrays as the parameters of the type as you intended, one would expect to use static arrays.

For instance, this is type-stable as well:

```julia
julia> using StaticArrays

julia> struct me{I,O}
               a::Vector{SVector{Float32,I}}
               b::Vector{SVector{Float32,O}}
       end

```

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 20, 2021, 5:39pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/4 "2021-01-20T17:39:09Z")

</div>

Interesting point. Thank you for the answer.  
I tested it with the struct you described and it gives:

```julia
Body::AbstractVector{var"#s827"} where var"#s827"
1 ─ %1 = Core.apply_type(Main.Array, Main.Float32, 3)::Core.Const(Array{Float32, 3})
│ %2 = Core.apply_type(Main.Vector, %1)::Core.Const(Vector{Array{Float32, 3}})
│ %3 = Core.apply_type(Main.Array, Main.Float32, 2)::Core.Const(Matrix{Float32})
│ %4 = Core.apply_type(Main.Vector, %3)::Core.Const(Vector{Matrix{Float32}})
│ %5 = Core.apply_type(Main.me, %2, %4)::Core.Const(me{Vector{Array{Float32, 3}}, Vector{Matrix{Float32}}})
│ %6 = Main.randn(Main.Float32, 2, 1, 1)::Array{Float32, 3}
│ %7 = Base.vect(%6)::Vector{Array{Float32, 3}}
│ %8 = Main.randn(Main.Float32, 2, 1)::Matrix{Float32}
│ %9 = Base.vect(%8)::Vector{Matrix{Float32}}
│ (m = (%5)(%7, %9))
│ %11 = Main.foo(m)::AbstractVector{var"#s827"} where var"#s827"
└── return %11

```

Instead of this:

```julia
Body::Vector{Array{Float32, 3}}
1 ─ %1 = Core.apply_type(Main.Array, Main.Float32, 3)::Core.Const(Array{Float32, 3})
│ %2 = Core.apply_type(Main.Vector, %1)::Core.Const(Vector{Array{Float32, 3}})
│ %3 = Core.apply_type(Main.Array, Main.Float32, 2)::Core.Const(Matrix{Float32})
│ %4 = Core.apply_type(Main.Vector, %3)::Core.Const(Vector{Matrix{Float32}})
│ %5 = Core.apply_type(Main.me, %2, %4)::Core.Const(me{Vector{Array{Float32, 3}}, Vector{Matrix{Float32}}})
│ %6 = Main.randn(Main.Float32, 2, 1, 1)::Array{Float32, 3}
│ %7 = Base.vect(%6)::Vector{Array{Float32, 3}}
│ %8 = Main.randn(Main.Float32, 2, 1)::Matrix{Float32}
│ %9 = Base.vect(%8)::Vector{Matrix{Float32}}
│ (m = (%5)(%7, %9))
│ %11 = Main.foo(m)::Vector{Array{Float32, 3}}
└── return %11

```

So I don’t think the struct has anything to do with the problem.

Btw, I am still looking for the answer why does this replacement of this  
`double(x::Vector{Array{Float32, 3}}) = 2 .* x` with this `double(x::Vector{Array{Float32, 3}}) = 2.f0 .* x` solves the problem.

By the way thank you for the StaticArrays idea, I never understood what is that and I will look after that too.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 20, 2021, 5:42pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/5 "2021-01-20T17:42:46Z")

</div>

Is this the same code as that of your MWE? I do not get that (and changing the 2 to 2.f0 does not change anything here). With the static arrays I get, from `@code_warntype`:

```julia
Body::Union{}
1 ─ %1 = Core.apply_type(Main.me, 3, 2)::Core.Compiler.Const(me{3,2}, false)
│ %2 = Main.randn(Main.Float32, 2, 3, 4)::Array{Float32,3}
│ %3 = Base.vect(%2)::Array{Array{Float32,3},1}
│ %4 = Main.randn(Main.Float32, 2, 4)::Array{Float32,2}
│ %5 = Base.vect(%4)::Array{Array{Float32,2},1}
│ (m = (%1)(%3, %5))
│ Main.foo(m)
└── Core.Compiler.Const(:(return %7), false)

```

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 20, 2021, 5:47pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/6 "2021-01-20T17:47:34Z")

</div>

Yeah, the problem is that if you replace the struct with

```julia
       struct me{I,O}
               a::I
               b::O
       end

```

then you have to replace the bar function:  
`m=me{3,2}([randn(Float32,2,3,4)],[randn(Float32,2,4)])`  
wtih this  
`m=me{Vector{Array{Float32,3}},Vector{Array{Float32,2}}}([randn(Float32,2,3,4)],[randn(Float32,2,4)])`

Because in the other case something strange happenes that is not equal with the test. ( Union{} in the return)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 20, 2021, 6:16pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/7 "2021-01-20T18:16:27Z")

</div>

Well, here is a more minimal example:

```julia
using InteractiveUtils

struct me{T}
  a::T
end

double(x) = 2 .* x

function bar()
  m=me([[0]])
  double(m.a)
end

@time bar();
@code_warntype bar()

double(x) = 2 .* x

@code_warntype bar()

```

I think that is definitely a bug.

Result:

```julia
  0.055437 seconds (163.06 k allocations: 8.348 MiB)
Variables
  #self#::Core.Compiler.Const(bar, false)
  m::me{Array{Array{Int64,1},1}}

Body::Union{BitArray{1}, Array}
1 ─ %1 = Base.vect(0)::Array{Int64,1}
│ %2 = Base.vect(%1)::Array{Array{Int64,1},1}
│ (m = Main.me(%2))
│ %4 = Base.getproperty(m, :a)::Array{Array{Int64,1},1}
│ %5 = Main.double(%4)::Union{BitArray{1}, Array}
└── return %5
Variables
  #self#::Core.Compiler.Const(bar, false)
  m::me{Array{Array{Int64,1},1}}

Body::Array{Array{Int64,1},1}
1 ─ %1 = Base.vect(0)::Array{Int64,1}
│ %2 = Base.vect(%1)::Array{Array{Int64,1},1}
│ (m = Main.me(%2))
│ %4 = Base.getproperty(m, :a)::Array{Array{Int64,1},1}
│ %5 = Main.double(%4)::Array{Array{Int64,1},1}
└── return %5

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [January 20, 2021, 6:34pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/8 "2021-01-20T18:34:10Z")

</div>

Hmmm… even minimaler on Julia 1.5:

```julia
julia> function bar()
         m=Ref([[0]])
         double(m[])
       end
bar (generic function with 1 method)

julia> double(x) = 2 .* x
double (generic function with 1 method)

julia> @code_warntype bar()
Variables
  #self#::Core.Compiler.Const(bar, false)
  m::Base.RefValue{Array{Array{Int64,1},1}}

Body::Union{BitArray{1}, Array}
1 ─ %1 = Base.vect(0)::Array{Int64,1}
│ %2 = Base.vect(%1)::Array{Array{Int64,1},1}
│ (m = Main.Ref(%2))
│ %4 = Base.getindex(m)::Array{Array{Int64,1},1}
│ %5 = Main.double(%4)::Union{BitArray{1}, Array}
└── return %5

julia> bar()
1-element Array{Array{Int64,1},1}:
 [0]

julia> double(x) = 2 .* x
double (generic function with 1 method)

julia> @code_warntype bar()
Variables
  #self#::Core.Compiler.Const(bar, false)
  m::Base.RefValue{Array{Array{Int64,1},1}}

Body::Array{Array{Int64,1},1}
1 ─ %1 = Base.vect(0)::Array{Int64,1}
│ %2 = Base.vect(%1)::Array{Array{Int64,1},1}
│ (m = Main.Ref(%2))
│ %4 = Base.getindex(m)::Array{Array{Int64,1},1}
│ %5 = Main.double(%4)::Array{Array{Int64,1},1}
└── return %5

```

> **different but similar on Julia master**
>
> ```julia
> julia> function bar()
> m=Ref([[0]])
> double(m[])
> end
> bar (generic function with 1 method)
> 
> julia> double(x) = 2 .* x
> double (generic function with 1 method)
> 
> julia> @code_warntype bar()
> Variables
> #self#::Core.Const(bar)
> m::Base.RefValue{Vector{Vector{Int64}}}
> 
> Body::AbstractVector{var"#s829"} where var"#s829"
> 1 ─ %1 = Base.vect(0)::Vector{Int64}
> │ %2 = Base.vect(%1)::Vector{Vector{Int64}}
> │ (m = Main.Ref(%2))
> │ %4 = Base.getindex(m)::Vector{Vector{Int64}}
> │ %5 = Main.double(%4)::AbstractVector{var"#s829"} where var"#s829"
> └── return %5
> 
> julia> bar()
> 1-element Vector{Vector{Int64}}:
> [0]
> 
> julia> double(x) = 2 .* x
> double (generic function with 1 method)
> 
> julia> @code_warntype bar()
> Variables
> #self#::Core.Const(bar)
> m::Base.RefValue{Vector{Vector{Int64}}}
> 
> Body::Vector{Vector{Int64}}
> 1 ─ %1 = Base.vect(0)::Vector{Int64}
> │ %2 = Base.vect(%1)::Vector{Vector{Int64}}
> │ (m = Main.Ref(%2))
> │ %4 = Base.getindex(m)::Vector{Vector{Int64}}
> │ %5 = Main.double(%4)::Vector{Vector{Int64}}
> └── return %5
> 
> ```

This feels familiar but I can’t find the issue on GitHub. Pretty sure there is one.

---

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [January 20, 2021, 8:40pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/9 "2021-01-20T20:40:32Z")

</div>

Prob [this one](https://github.com/JuliaLang/julia/issues/35537) and its relatives 🙂

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 20, 2021, 9:17pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/10 "2021-01-20T21:17:06Z")

</div>

Wow! I was like, I have the solution but that is some bug that shows it is not just in my one scenario. (Also I am on Julia 1.6.) I thought the problem was with the Int to Float32 conversion in my case, but this is even crazier.

Are there any idea what can be the problem there? I can think of:

- The type interference algotihm just doesn’t have the knowledge how to expand a (Int \* Array{Float64})
- Using .\* instead of \*
- Using [[1. 1.]] intead of [[1.]] also works

Any exact idea what can be the problem there? Julia type interference algorithm has a hard time at Type1{Type2{Type3}}, anything more then fitting 2 type.

---

<div class="post-metadata">

**Author:** ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)\
**Post date:** [January 20, 2021, 9:42pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/11 "2021-01-20T21:42:48Z")

</div>

I don’t think it’s any of the bullet pointed things, those are trivial under normal circumstances. Clicking through the related GitHub issues left me with the impression, that this may be an unfortunate combination of the compiler giving up on inference at some point (either because of some some time-to-first-plot optimization that makes inference stop after enough nesting steps to reduce time, or because of some overlooked buggy recursion there) and caching (parts of) the inference results so far. I guess that may lead to correct inference on the second try, if cached stuff somehow solves the problem that occured in the first place. But this is really just a guess, one would have to know exactly why and where it fails to infer in the first place.

---

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [January 21, 2021, 2:54pm UTC](https://discourse.julialang.org/t/how-code-warntype-precompilation-execution-and-type-interference-works/53674/12 "2021-01-21T14:54:38Z")

</div>

Yes, given [Jeff’s response](https://github.com/JuliaLang/julia/issues/35800#issuecomment-702433366), I don’t think we will be solving it on discourse anytime soon 😆
