# Spooky Missing action at a distance

**URL:** <https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089>\
**Category:** General Usage\
**Created:** [February 15, 2018, 6:28pm UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089 "2018-02-15T18:28:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jamii](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jamii/32/1373_2.png) [@jamii](https://discourse.julialang.org/u/jamii)\
**Post date:** [February 15, 2018, 6:28pm UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/1 "2018-02-15T18:28:53Z")

</div>

I understand _why_ this happens, but it surprised me. Some complex code that was previously type-stable became unstable after upgrading unrelated dependencies. I’m not really sure what I think about this - I’m just posting it here for the sake of discussion.

```julia
julia> foo() = x != 1
foo (generic function with 1 method)

julia> @code_warntype foo()
Variables:
  #self# <optimized out>

Body:
  begin 
      SSAValue(0) = Main.x
      $(Expr(:inbounds, false))
      # meta: location operators.jl != 129
      SSAValue(1) = (Core.typeassert)((SSAValue(0) == 1)::Any, Base.Bool)::Bool
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return (Base.not_int)(SSAValue(1))::Bool
  end::Bool

julia> using Missings

julia> @code_warntype foo()
Variables:
  #self# <optimized out>

Body:
  begin 
      return (Main.x != 1)::Union{Bool, Missings.Missing}
  end::Union{Bool, Missings.Missing}

```

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [February 15, 2018, 6:34pm UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/2 "2018-02-15T18:34:11Z")

</div>

I think that in general this _has_ to happen when new methods are added. The only alternative I can see would be globally enforcing return types on all methods of a particular function which is definitely not going to happen. It should go without saying that if you tell the compiler the type of `x`, for example by doing `const x = 1`, the return type goes back to being type-stable even in the presence of `Missings`.

---

<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:** [February 21, 2018, 7:14am UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/3 "2018-02-21T07:14:36Z")

</div>

This has nothing to do with `Missings` _per se_, you can get something similar with eg

```julia
julia> foo(x::Int) = 1
foo (generic function with 1 method)

julia> bar() = foo(x)
bar (generic function with 1 method)

julia> @code_warntype bar()
Variables:
  #self# <optimized out>

Body:
  begin 
      return (Main.foo)(Main.x)::Int64
  end::Int64

julia> foo(x::Float64) = 1.0
foo (generic function with 2 methods)

julia> @code_warntype bar()
Variables:
  #self# <optimized out>

Body:
  begin 
      return (Main.foo)(Main.x)::Union{Float64, Int64}
  end::Union{Float64, Int64}

```

Don’t use globals.

---

<div class="post-metadata">

**Author:** ![jamii](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jamii/32/1373_2.png) [@jamii](https://discourse.julialang.org/u/jamii)\
**Post date:** [February 21, 2018, 11:30am UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/4 "2018-02-21T11:30:34Z")

</div>

> Don’t use globals.

Sure. Globals are just the simplest example I could come up with.

I actually ran into this in the output of a query compiler. For some reason  
queries were allocating more memory if they were run on data had been  
loaded from disk. Turns out this is because I have some Any==Any  
comparisons when data is pulled from the execution graph and suddenly those  
are now inferred as Union{Bool, Missing} which causes boxing and generic  
calls downstream.

As Expanding Man said, this is probably an unavoidable consequence of  
Julia’s design. I’m not demanding something be done. This was just “hey  
this caught me out, be aware, sometimes == doesn’t return a boolean,  
depending on what packages you have loaded”.

---

<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:** [February 21, 2018, 11:53am UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/5 "2018-02-21T11:53:42Z")

</div>

> [@jamii](#):
>
> this is because I have some `Any==Any` comparisons when data is pulled from the execution graph and suddenly those are now inferred as Union{Bool, Missing} which causes boxing and generic calls downstream.

It would be interesting to see an MWE of what you are doing. I expect that you would need a (potential) `missing` somewhere to infer a `Union{Bool, Missing}`, and it is not clear to me why you need that in a query compiler (or you could have found a bug in inference).

As a quick fix, you could use a different comparison (possibly defining your own), that always returns boolean.

---

<div class="post-metadata">

**Author:** ![jamii](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jamii/32/1373_2.png) [@jamii](https://discourse.julialang.org/u/jamii)\
**Post date:** [February 21, 2018, 3:14pm UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/6 "2018-02-21T15:14:42Z")

</div>

> I expect that you would need a (potential) missing somewhere to infer a Union{Bool, Missing}

The potential `Missing` comes from `Missing <: Any`, just like in the first example I posted.

The query code is in theory type-stable, but sometimes inference bails out (eg from hitting MAX\_TYPE\_DEPTH if I nest too many closures) and I get return\_value::ANY and then Union{Bool, Missing} down the line.

Again, I’m not presenting this as a problem to be fixed. I know how to fix my own code and the changing inference is a necessary consequence of Julia’s design. I’m just making a note of something that confused me for a while, so that if other people run into it they can find the explanation and skip the debugging time.

---

<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:** [February 22, 2018, 10:40am UTC](https://discourse.julialang.org/t/spooky-missing-action-at-a-distance/9089/7 "2018-02-22T10:40:26Z")

</div>

My point was that, in a context where you are not using globals and the compiler can infer that the type of the values you are comparing cannot be `Missing`, this whole issue should go away (apart from the compiler not being smart enough to prove something, but `v0.7` is becoming amazing in that respect).

Are you relying on the result of type inference in any way?
