Search code examples
genericsreturn-typehacklang

Hacklang: Cannot return Vector from (function(...): KeyedIterable<arraykey, mixed>)


I have a method that might return either a Map or a Vector, and since both types implement KeyedIterableVector<T> specifically implementing KeyedIterable<int, T> — I figured I could cover both cases with a KeyedIterable<arraykey, T> return type. However, even though arraykey is a more general type than int, this doesn't work. For example, the typechecker complains on the following code:

<?hh // strict
class A {
   public static function foo(): KeyedIterable<arraykey, mixed> {
      return Vector{};
      /*
      Invalid return type (Typing[4110])
      This is an array key (int/string)
      It is incompatible with an int
      Considering that this type argument is invariant with respect to KeyedIterable
      */
   }
}

Why can't I do this?


Solution

  • This is because KeyedIterable isn't read-only, so can't take a subtype.

    For instance, A::foo()->toMap() will have the type Map<arraykey, mixed> from the type signatures, but the actual type Map<int, mixed>.