# Type inference broken?

**URL:** <https://discourse.julialang.org/t/type-inference-broken/5373>\
**Category:** Internals & Design\
**Created:** [August 14, 2017, 9:43am UTC](https://discourse.julialang.org/t/type-inference-broken/5373 "2017-08-14T09:43:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![klacru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klacru/32/27890_2.png) [@klacru](https://discourse.julialang.org/u/klacru)\
**Post date:** [August 14, 2017, 9:43am UTC](https://discourse.julialang.org/t/type-inference-broken/5373/1 "2017-08-14T09:43:11Z")

</div>

Motivation:  
Imagine I want to use the return type of a function to define an output array of that type.

```julia
julia> makearray(f::Function, ::Type{T}) where T = 
                                         Core.Inference.return_type(f, (T,T))[]
makearray (generic function with 3 methods)

julia> makearray(cmp, Int)
0-element Array{Int64,1}

julia> makearray(cmp, Integer)
0-element Array{Any,1}

julia> which(cmp, (Integer, Integer))
cmp(x::Integer, y::Integer) in Base at operators.jl:348

julia> which(cmp, (Int, Int))
cmp(x::Integer, y::Integer) in Base at operators.jl:348

```

The result is as I expected with `Int`, but fails with `Integer`. That is due to `Core..return_type`.  
The used method is the same in both cases:

```julia
operators.jl:348
# cmp returns -1, 0, +1 indicating ordering
cmp(x::Integer, y::Integer) = ifelse(isless(x, y), -1, ifelse(isless(y, x), 1, 0))

```

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 14, 2017, 9:54am UTC](https://discourse.julialang.org/t/type-inference-broken/5373/2 "2017-08-14T09:54:32Z")

</div>

No, inference is not broken as it correctly infers that the return type of `cmp(<:Integer,<:Integer)` must be a subtype of `Any`. But sure, there is room for improvement.

Also, note that it is discouraged to make your program dependent on inference; one of the reasons being because inference might get better in the future and your program may then fail.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [August 14, 2017, 12:21pm UTC](https://discourse.julialang.org/t/type-inference-broken/5373/3 "2017-08-14T12:21:21Z")

</div>

> [@mauro3](#):
>
> But sure, there is room for improvement.

Is there?

---

<div class="post-metadata">

**Author:** ![klacru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klacru/32/27890_2.png) [@klacru](https://discourse.julialang.org/u/klacru)\
**Post date:** [August 14, 2017, 6:10pm UTC](https://discourse.julialang.org/t/type-inference-broken/5373/4 "2017-08-14T18:10:08Z")

</div>

I view the current situation as a conservative approach:  
Also if all current implementations of `cmp` clearly return `Int64`, and also if I call `invoke` to get the implementation for the abstract `Integer`, there is no guarantee, that in the future, somebody implements for a new subtype of `Integer` a methods with a different return type.  
But being conservative is not a typical approach for Julia, I suppose.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [August 14, 2017, 6:20pm UTC](https://discourse.julialang.org/t/type-inference-broken/5373/5 "2017-08-14T18:20:45Z")

</div>

> [@klacru](#):
>
> Also if all current implementations of cmp clearly return Int64, and also if I call invoke to get the implementation for the abstract Integer, there is no guarantee, that in the future, somebody implements for a new subtype of Integer a methods with a different return type.

No that’s not the reason. There are just too many matching methods.

---

<div class="post-metadata">

**Author:** ![klacru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klacru/32/27890_2.png) [@klacru](https://discourse.julialang.org/u/klacru)\
**Post date:** [August 14, 2017, 7:16pm UTC](https://discourse.julialang.org/t/type-inference-broken/5373/6 "2017-08-14T19:16:30Z")

</div>

That does not sound like a big obstacle! I my example there are 6: `method(cmp, (Integer, Integer)`. But in general, there is no limit, except given of the size of the code base.  
For the moment, I will stick to my work-around. I force a concrete type to be used, by changing the signature to:

```julia
julia> makearray(f::Function, ::T) where T = Core.Inference.return_type(f, (T,T))[]
makearray (generic function with 1 method)
julia> makearray(cmp, BigFloat(0))
0-element Array{Int64,1}

```

Only need a handy object at times.

---

<div class="post-metadata">

**Author:** ![PabloZubieta](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@PabloZubieta](https://discourse.julialang.org/u/PabloZubieta)\
**Post date:** [August 14, 2017, 7:26pm UTC](https://discourse.julialang.org/t/type-inference-broken/5373/7 "2017-08-14T19:26:55Z")

</div>

> Imagine I want to use the return type of a function to define an output array of that type.

The following describes how this is handled generally in Base to have inference-independent behavior (except for empty arrays), avoiding what @mauro3 pointed above. Granted, it won’t be generally inferable but it will give you a tight element-typed-array when not inferable.

> [@Alternatives to \`Base.promote\_op(op, ::Type...)\` for \`op::Type\`?](https://discourse.julialang.org/t/alternatives-to-base-promote-op-op-type-for-op-type/5289/8):
>
> The behavior of promote\_op was initially intended for some operations between arrays and scalars and for broadcast, but we’ve gradually moved from relying on it. The general strategy in Base when we want to rely on inference for predicting, for example, the element type of an array is the following: Use Core.Inference.return\_type or related functions to get an idea of the return type R. If R is concrete, go ahead, use that. If that is not the case and your array is empty, then also use R. Othe…
