# Type inference when types are passed as values

**URL:** <https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539>\
**Category:** General Usage\
**Tags:** inference\
**Created:** [June 8, 2018, 2:30pm UTC](https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539 "2018-06-08T14:30:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![alpharho](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@alpharho](https://discourse.julialang.org/u/alpharho)\
**Post date:** [June 8, 2018, 2:30pm UTC](https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539/1 "2018-06-08T14:30:10Z")

</div>

I got a little confused about how type inference works, when trying to find out what happens when types are passed as values to a function like in `rand(Int64)`. So far I thought that the compiler tries to infer the returned type of a function only using `typeof(arg)` for every argument `arg`. However, to me it seems that that then e.g. `code_warntype(rand, (typeof(Int64), ))` and `@code_warntype rand(Int64)` would have to be equivalent, while actually they give different results (the following is in v0.6.2 but the same happens in the 0.7 alpha):

```julia
julia> @code_warntype rand(Int64)
Variables:
  #self# <optimized out>
  T <optimized out>

Body:
  begin 
      $(Expr(:inbounds, false))
      # meta: location random.jl rand 358
      SSAValue(0) = $(Expr(:invoke, MethodInstance for rand(::MersenneTwister, ::Type{UInt64}), :(Base.Random.rand), :(Base.Random.GLOBAL_RNG), :(Base.Random.UInt64)))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return (Base.bitcast)(Int64, SSAValue(0))
  end::Int64

```

where the type is inferred correctly and

```julia
julia> code_warntype(rand, (typeof(Int64), ))
Variables:
  #self# <optimized out>
  T::DataType

Body:
  begin 
      return (Base.Random.rand)(Base.Random.GLOBAL_RNG, T::DataType)::Any
  end::Any

```

where it is not. This doesn’t seem to fit the documentation of @code\_warntype, which states, that it “Evaluates the arguments to the function or macro call, determines their types, and calls code\_warntype on the resulting expression.”.

I didn’t find any questions on discourse about this. In the documentation I found out about the singleton types `Type{T}` and that you can specialize methods on type values with that (which apparently is the case for `rand`) but I don’t see how this fits into inference.

Also, as `code_warntype` is the only way I know to get information about type inference, I’m not sure whether this is a question about `code_warntype` or about type inference. I think my confusion boils down to the following two questions though:

1. Is it wrong to say that the compiler only uses information in `typeof.(args)` during inference?
2. When checking for type stability, should I trust `@code_warntype` or `code_warntype()`?

---

<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:** [June 8, 2018, 2:45pm UTC](https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539/2 "2018-06-08T14:45:23Z")

</div>

Great question. Yes, types are very special — their `typeof` is `DataType`, but they’re also subtypes of the very special `Type`, which can be parameterized to match one particular type. So, yes, it is wrong to say the compiler only uses `typeof` — it uses `Core.Typeof`.

As far as its trust-worthiness, we do try to keep it as accurate as possible. There are indeed some gotchas, though, particularly when it comes to functions that inline into their caller. For example, on 0.7:

```julia
julia> g(x) = x ? 1 : "one"
g (generic function with 1 method)

julia> @code_warntype g(true)
Body::Union{Int64, String}
1 1 ─ goto 3 if not %%x │
  2 ─ return 1 │
  3 ─ return "one" │

```

This function `g` is type unstable! But watch what happens when you call it from another function with a constant:

```julia
julia> f() = g(true)
f (generic function with 1 method)

julia> @code_warntype f()
Body::Int64
1 1 ─ return 1 │

```

Julia was able to infer `g` when called by a constant value — even though `g` itself isn’t type stable!

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [June 8, 2018, 3:16pm UTC](https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539/3 "2018-06-08T15:16:17Z")

</div>

As for how this is implemented, it looks like `@code_warntype` (and other macros) use the unexported `Base.typesof(args)` instead of `typeof.(args)` to do this, [https://github.com/JuliaLang/julia/blob/795626d0018a5d3d13c471ca81409fd0d021d3f7/stdlib/InteractiveUtils/src/macros.jl](https://github.com/JuliaLang/julia/blob/795626d0018a5d3d13c471ca81409fd0d021d3f7/stdlib/InteractiveUtils/src/macros.jl) (`gen_call_with_extracted_types` function, called from the macros here, [https://github.com/JuliaLang/julia/blob/795626d0018a5d3d13c471ca81409fd0d021d3f7/stdlib/InteractiveUtils/src/macros.jl#L70](https://github.com/JuliaLang/julia/blob/795626d0018a5d3d13c471ca81409fd0d021d3f7/stdlib/InteractiveUtils/src/macros.jl#L70)).

Edit: ah, `Base.typesof` calls `Core.Typeof` on master, as @mbauman mentioned.

---

<div class="post-metadata">

**Author:** ![alpharho](https://avatars.discourse-cdn.com/v4/letter/a/71e660/32.png) [@alpharho](https://discourse.julialang.org/u/alpharho)\
**Post date:** [June 12, 2018, 12:39pm UTC](https://discourse.julialang.org/t/type-inference-when-types-are-passed-as-values/11539/4 "2018-06-12T12:39:50Z")

</div>

Thanks for the quick answer! Is there a specific reason, why there are two different `"typeof"`s?
