# @code\_warntype fails when function has a keyword argument

**URL:** https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907
**Category:** New to Julia
**Created:** [March 15, 2019, 10:00am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907 "2019-03-15T10:00:57Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)
#### Post date: [March 15, 2019, 10:00am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/1 "2019-03-15T10:00:58Z")

</div>

In the following two functions are identical except that `fun2()` has a keyword argument. However, `@code_warntype` fails to “go into” the `invoke Main...` part that should give a warntype!

```julia
function fun1(v)
    kw = 1
    println(v[1])
end

function fun2(v; kw=1)
    println(v[1])
end

v = Vector{Real}(undef, 2)
v[1] = 1
v[2] = 2.2

julia> @code_warntype fun1(v)
Body::Nothing
1 ─ %1 = (Base.arrayref)(true, v, 1)::Real
│ %2 = (Main.println)(%1)::Core.Compiler.Const(nothing, false)
└── return %2

julia> @code_warntype fun2(v)
Body::Nothing
1 ─ %1 = invoke Main.:(#fun2#3)(1::Int64, _1::Function, _2::Array{Real,1})::Core.Compiler.Const(nothing, false)
└── return %1

```

it’s worrisome…

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 15, 2019, 10:51am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/2 "2019-03-15T10:51:52Z")

</div>

> [@tomtom](#):
>
> `@code_warntype` fails to “go into” the `invoke Main...` part that should give a warntype!

This is not a failure — `@code_warntype` does not expand the callees recursively (unless they were inlined).

Just use `@code_warntype fun2(v; kw = 1)`.

Also, note that if you are debugging type stablity, you should use arguments with concrete types. Abstract type parameters like in `Vector{Real}` preclude the optimizations that are allowed by knowing types at compile time (“type stability”), so are not really relevant.

---

<div class="post-metadata">

### Author: ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)
#### Post date: [March 15, 2019, 11:29am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/3 "2019-03-15T11:29:18Z")

</div>

You can use [Cthulhu](https://github.com/JuliaDebug/Cthulhu.jl) to descend into ~~madness~~ functions with keyword arguments (among other things):

```julia
julia> @descend_code_typed fun2(v)

│ ─ %-1 = invoke fun2(::Array{Real,1})::Core.Compiler.Const(nothing, false)
CodeInfo(
    @ REPL[2]:2 within `fun2'
1 ─ %1 = invoke Main.:(#fun2#3)(1::Int64, _1::Function, _2::Array{Real,1})::Core.Compiler.Const(nothing, false)
└── return %1
)
Select a call to descend into or ↩ to ascend. [q]uit.
Toggles: [o]ptimize, [w]arn, [d]ebuginfo.
Show: [L]LVM IR, [N]ative code
Advanced: dump [P]arams cache.

 • %1 = invoke #fun2#3(::Int64,::Function,::Array{Real,1})
   ↩

│ ─ %-1 = invoke #fun2#3(::Int64,::Function,::Array{Real,1})::Core.Compiler.Const(nothing, false)
CodeInfo(
    @ REPL[2]:2 within `#fun2#3'
   ┌ @ array.jl:729 within `getindex'
1 ─│ %1 = (Base.arrayref)(true, v, 1)::Real
│ └
│ %2 = (Main.println)(%1)::Core.Compiler.Const(nothing, false)
└── return %2
)
Select a call to descend into or ↩ to ascend. [q]uit.
Toggles: [o]ptimize, [w]arn, [d]ebuginfo.
Show: [L]LVM IR, [N]ative code
Advanced: dump [P]arams cache.

 • ↩

```

---

<div class="post-metadata">

### Author: ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)
#### Post date: [March 15, 2019, 11:42am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/4 "2019-03-15T11:42:45Z")

</div>

> [@mateuszbaran](#):
>
> You can use [Cthulhu](https://github.com/JuliaDebug/Cthulhu.jl)

thanks. could you show how to install this package?

---

<div class="post-metadata">

### Author: ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)
#### Post date: [March 15, 2019, 11:45am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/5 "2019-03-15T11:45:57Z")

</div>

It’s not registered, so you have to do `add https://github.com/JuliaDebug/Cthulhu.jl` in [Pkg mode](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html).

---

<div class="post-metadata">

### Author: ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)
#### Post date: [March 15, 2019, 11:54am UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/6 "2019-03-15T11:54:51Z")

</div>

that `Vector{Real}` is intentional (or else no warntype to show at all).

with `@code_warntype` not recursively gives warning, we would need to **carefully watch out** any `invoke`. Or, use [Cthulhu](https://github.com/JuliaDebug/Cthulhu.jl) as @mateuszbaran suggested.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 15, 2019, 12:15pm UTC](https://discourse.julialang.org/t/code-warntype-fails-when-function-has-a-keyword-argument/21907/7 "2019-03-15T12:15:46Z")

</div>

Perhaps you misunderstand the role of `@code_warntype`: the idea is that it helps you detect type instabilities when you call with concrete types. This will be marked even if we don’t descend into the callees. Eg

```julia
julia> @noinline f(x) = x > 0 ? 1 : 1.0
f (generic function with 1 method)

julia> g(x) = f(x^2)
g (generic function with 1 method)

julia> @code_warntype g(1)
Variables
  #self#::Core.Compiler.Const(g, false)
  x::Int64

Body::Union{Float64, Int64}
1 ─ %1 = Core.apply_type(Base.Val, 2)::Core.Compiler.Const(Val{2}, false)
│ %2 = (%1)()::Core.Compiler.Const(Val{2}(), false)
│ %3 = Base.literal_pow(Main.:^, x, %2)::Int64
│ %4 = Main.f(%3)::Union{Float64, Int64}
└── return %4

```

where the `::Union{Float64, Int64}` is highlighted if the terminal supports it. So you are not going to miss anything.
