Does `==(::Missing, ::Any)=missing` violate type stability?

(The intent of this question is to improve my understanding of type stability, not criticize the language design.)

Most comparisons, like 0==0 and false==1 and so on return a Bool, but comparisons with missing return missing by design. This creates a gotcha in writing generic code with if statements, because for arbitrary input a==b could be Bool or Missing (and therefore if a==b could be an error). Doesn’t this violate the principles of type stability?

Type stability means if the return type can predicted from the types of the arguments. No this does not violate type stability. If one the arguments are of type Missing then you can predict the return type will be Missing.

4 Likes

To add on this, this is the conventional notion of type stability as a property of a method: given concrete types in, known return type out. ==(::Missing, ::Any) is type-stable because just given the first concrete missing, it could only return missing.

A looser notion of type stability applies to whether a variable or expression can be inferred to have a fixed concrete type at compile-time. When people are being precise, they say “inferable”/“has an inferable type” rather than “type-stable”, though it is accurate to say that the return type of a type-stable method is inferable.

I think the latter is what OP is getting at. If a is known to be missing, then the expression a==b is known to be missing. But if a is not inferable because it could be 1 or "foo", a==b is not inferable either and will dispatch to == methods at run-time.

1 Like

In other words, if I write code containing an instance of a==b that could dispatch to either ==(::Any, ::Any) or ==(::Missing, ::Any) at runtime, then my code might be bad, but this doesn’t mean that the methods themselves are type unstable?

1 Like

Yeah, that’s exactly right. If your code looks like:

function foo()
  if rand() < 0.5
    x = "hello"
  else
    x = missing
  end

  if  x == missing
    do_stuff()
  end
end

then the type of x can’t be concretely inferred, but it’s not =='s fault.

1 Like