Alternatives to `Base.promote_op(op, ::Type...)` for `op::Type`?

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:

  1. Use Core.Inference.return_type or related functions to get an idea of the return type R.
  2. If R is concrete, go ahead, use that.
  3. If that is not the case and your array is empty, then also use R.
  4. Otherwise, you get the type of the first element T and construct an array of that type and define a recursive function that iterates and fills the elements of the array as long as each type S is a subtype of the element type of the array. If that is not the case, you convert your array to an array of type typejoin(T, S) and continue from where you left off (calling the recursive function with the new array) until your fill the array.

You can write a similar function to the one in step 4, and avoid using Core.Inference.return_type at all, except that it won’t handle the empty case.

There are other scenarios where you might want inference to help you to determine a type beforehand, e.g., you want to know the type of the field of an object you’re going to construct (Nullables are an example of this), in that case Core.Inference.return_type might be as best as it can get.

NOTE: This is not an advice encouraging anyone using Core.Inference.return_type whenever they want. It’s not exported for a reason. But in the case it’s really needed, people should try an approach similar to the one described above if possible.

4 Likes