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; }