# Inspect inferred types and generated codes for inner functions

**URL:** <https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688>\
**Category:** General Usage\
**Tags:** question, performance, code\_warntype, functional\
**Created:** [March 10, 2022, 2:22pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688 "2022-03-10T14:22:41Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Uroc327](https://avatars.discourse-cdn.com/v4/letter/u/eb8c5e/32.png) [@Uroc327](https://discourse.julialang.org/u/Uroc327)\
**Post date:** [March 10, 2022, 2:22pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/1 "2022-03-10T14:22:41Z")

</div>

Often it is convenient to have inner functions, eg for functional ones like `mapreduce`. How can I apply code inspection macros like `@code_llvm` or `@code_warntype` to the “full” function?

Example:

```julia
julia> function test(a)
           inner() = a + 3
           inner()
       end
test (generic function with 1 method)

julia> @code_warntype test(3)
Variables
  #self#::Core.Const(test)
  a::Int64
  inner::var"#inner#1"{Int64}

Body::Int64
1 ─ %1 = Main.:(var"#inner#1")::Core.Const(var"#inner#1")
│ %2 = Core.typeof(a)::Core.Const(Int64)
│ %3 = Core.apply_type(%1, %2)::Core.Const(var"#inner#1"{Int64})
│ (inner = %new(%3, a))
│ %5 = (inner)()::Int64
└── return %5

```

In that case, I can see that `inner` returns `Int64`. But when `inner` is more complex, it can still have type problems even when the final return type is inferred ok. Also, when one wants to inspect the generated code, how can one do this?

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [March 10, 2022, 2:45pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/2 "2022-03-10T14:45:43Z")

</div>

One way would be to use the debugger, put a breakpoint right after the definition of the inner function and use `@code_warntype` from within the debugger.

In practice, I tend to use a more hacky way: manually “exflitrate” the inner function in the global scope, so that it can be inspected from the REPL:

```julia
julia> function test(a)
           inner() = a + 3
           global TEST_INNER=inner
       
           inner()
       end
test (generic function with 1 method)

julia> test(3)
6

julia> @code_warntype TEST_INNER()
MethodInstance for (::var"#inner#1"{Int64})()
  from (::var"#inner#1")() in Main at REPL[1]:2
Arguments
  #self#::var"#inner#1"{Int64}
Body::Int64
1 ─ %1 = Core.getfield(#self#, :a)::Int64
│ %2 = (%1 + 3)::Int64
└── return %2

```

  

But none of this entirely satisfies me (\*), so I’m also interested in what others have to say about this: maybe there is some tooling that I don’t know about…

_(\*) one thing that bothers me in particular is that both those techniques require the outer function to actually be executed_

---

<div class="post-metadata">

**Author:** ![Uroc327](https://avatars.discourse-cdn.com/v4/letter/u/eb8c5e/32.png) [@Uroc327](https://discourse.julialang.org/u/Uroc327)\
**Post date:** [March 10, 2022, 3:46pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/3 "2022-03-10T15:46:42Z")

</div>

> [@ffevotte](#):
>
> In practice, I tend to use a more hacky way: manually “exflitrate” the inner function in the global scope, so that it can be inspected from the REPL

Does that still work for functions with closures and inside a module?

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [March 10, 2022, 7:50pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/4 "2022-03-10T19:50:39Z")

</div>

Yes, it should. The example above is already a closure (`inner` closes over `a`), and adding modules into the mix does change much:

```julia
julia> module Foo
           function foo(a)
               inner() = rand() > a ? a : false # a type-unstable inner function
               global TEST_INNER = inner
       
               inner()
           end
       end
Main.Foo

julia> Foo.foo(2)
false

julia> @code_warntype Foo.TEST_INNER()
MethodInstance for (::Main.Foo.var"#inner#1"{Int64})()
  from (::Main.Foo.var"#inner#1")() in Main.Foo at REPL[1]:4
Arguments
  #self#::Main.Foo.var"#inner#1"{Int64}
Body::Union{Bool, Int64}
1 ─ %1 = Main.Foo.rand()::Float64
│ %2 = Core.getfield(#self#, :a)::Int64
│ %3 = (%1 > %2)::Bool
└── goto #3 if not %3
2 ─ %5 = Core.getfield(#self#, :a)::Int64
└── return %5
3 ─ return false

```

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [March 10, 2022, 7:54pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/5 "2022-03-10T19:54:34Z")

</div>

As far as I understand that is what [Cthulhu.jl](https://github.com/JuliaDebug/Cthulhu.jl) is for?

OK, so maybe I should elaborate: I tried Cthulhu in the past and it seems to me pretty intimidating, a manual process similar to the use of the debugger @ffevotte is describing. So this would be some kind of last resort for me.

I prefer to using a profiler and `JET.jl` to spot irregularities.

As to the other questions: there are `@code_typed`, `@code_lowered`, `@code_llvm` and `@code_native` which allow to inspect the whole compilation pipeline.

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [March 11, 2022, 1:58pm UTC](https://discourse.julialang.org/t/inspect-inferred-types-and-generated-codes-for-inner-functions/77688/6 "2022-03-11T13:58:04Z")

</div>

> [@goerch](#):
>
> I tried Cthulhu in the past and it seems to me pretty intimidating

For me, watching this JuliaCon video helped a bunch.

[![](https://global.discourse-cdn.com/julialang/original/3X/d/2/d205f0b654c3c084ba11e1aadc3df08966a45929.jpeg "JuliaCon 2019 | Static walks through dynamic programs | Valentin Churavy") ](https://www.youtube.com/watch?v=qf9oA09wxXY)

Once you get your head around the menus, it becomes a lot clearer
