public function getLeastSuperType(PhpType $that)
 {
     if ($that->isArrayType()) {
         if ($this->isSubtypeOf($that)) {
             // We have a special case, that is if we compare array<unknown> to array<all>. Although, both types are
             // subtypes of each other, we always must have a predictable outcome of this method regardless of the
             // order of types, i.e. $a->getLeastSuperType($b) === $b->getLeastSuperType($a).
             if ($this->elementType->isUnknownType() && $that->elementType->isAllType()) {
                 return $this;
             }
             if ($that->elementType->isUnknownType() && $this->elementType->isAllType()) {
                 return $that;
             }
             return parent::getLeastSuperType($that);
         }
         $genericArrayType = $this->registry->getNativeType('array');
         if ($this === $genericArrayType) {
             return $this;
         }
         if ($that === $genericArrayType) {
             return $that;
         }
         // If both arrays have different item types defined, we keep them as
         // separate arrays in a union type. It can be used as an indication
         // that a key is not always defined.
         if (count($this->itemTypes) !== count($that->itemTypes) || (bool) array_diff_key($this->itemTypes, $that->itemTypes)) {
             return parent::getLeastSuperType($that);
         }
         $keyType = $this->registry->createUnionType(array($this->keyType, $that->keyType));
         $elementType = $this->registry->createUnionType(array($this->elementType, $that->elementType));
         $itemTypes = array();
         foreach ($this->itemTypes as $name => $itemType) {
             $itemTypes[$name] = $this->registry->createUnionType(array($itemType, $that->itemTypes[$name]));
         }
         return $this->registry->getArrayType($elementType, $keyType, $itemTypes);
     }
     return parent::getLeastSuperType($that);
 }
 public function isSubTypeOf(PhpType $that)
 {
     if ($that->isUnknownType()) {
         return true;
     }
     if ($that->isAllType()) {
         return true;
     }
     foreach ($this->alternates as $element) {
         if (!$element->isSubTypeOf($that)) {
             return false;
         }
     }
     return true;
 }