From 905a21f38226f7baa95bfc018292dbf6f1094974 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 18 Dec 2022 23:01:56 +0100 Subject: [PATCH] Simplify --- .../InitializerExprTypeResolver.php | 76 ++++--------------- .../OversizedConstantArrayTypeException.php | 10 --- 2 files changed, 13 insertions(+), 73 deletions(-) delete mode 100644 src/Reflection/OversizedConstantArrayTypeException.php diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 295053eeca9..9c9d310116e 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -64,12 +64,11 @@ use PHPStan\Type\TypeUtils; use PHPStan\Type\TypeWithClassName; use PHPStan\Type\UnionType; +use PHPStan\Type\VerbosityLevel; use function array_keys; -use function array_shift; use function array_values; use function count; use function dirname; -use function get_class; use function in_array; use function is_float; use function is_int; @@ -449,11 +448,7 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type { // degrade oversized constant arrays, supports only basic types. less precise but slim and fast. if (count($expr->items) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { - try { - return $this->builtDegradedConstantArray($expr, $getTypeCallback); - } catch (OversizedConstantArrayTypeException) { - // array contains items which we cannot infer the types for - } + return $this->buildDegradedConstantArray($expr, $getTypeCallback); } // more precise but less performant array resolving @@ -516,86 +511,41 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type /** * @param callable(Expr): Type $getTypeCallback - * - * @throws OversizedConstantArrayTypeException */ - private function builtDegradedConstantArray(Array_ $node, callable $getTypeCallback): Type + private function buildDegradedConstantArray(Array_ $node, callable $getTypeCallback): Type { $isList = true; - $isEmptyArray = true; - $isKeysNonEmptyString = true; - $isValuesNonEmptyString = true; - $valueTypes = []; - $itemKeyTypes = []; + $keyTypes = []; foreach ($node->items as $item) { if ($item === null) { - continue; + throw new ShouldNotHappenException(); } - $isEmptyArray = false; - $key = $item->key; if ($key !== null) { $isList = false; $itemKeyType = $getTypeCallback($key); - if (!$itemKeyType instanceof ConstantScalarType || $key instanceof ClassConstFetch) { - throw new OversizedConstantArrayTypeException(); - } - if (!$itemKeyType->isNonEmptyString()->yes()) { - $isKeysNonEmptyString = false; - } - $generalizedType = $itemKeyType->generalize(GeneralizePrecision::lessSpecific()); - $itemKeyTypes[get_class($generalizedType)] = $generalizedType; // de-duplicate values - } else { - $isKeysNonEmptyString = false; + $generalizedKeyType = $itemKeyType->generalize(GeneralizePrecision::moreSpecific()); + $keyTypes[$generalizedKeyType->describe(VerbosityLevel::precise())] = $generalizedKeyType; } $value = $item->value; - if ($value instanceof Array_) { - $valueTypes[] = $this->builtDegradedConstantArray($value, $getTypeCallback); - continue; - } - $itemValueType = $getTypeCallback($value); - if (!$itemValueType instanceof ConstantScalarType || $value instanceof ClassConstFetch) { - throw new OversizedConstantArrayTypeException(); - } - if (!$itemValueType->isNonEmptyString()->yes()) { - $isValuesNonEmptyString = false; - } - $generalizedType = $itemValueType->generalize(GeneralizePrecision::lessSpecific()); - $valueTypes[get_class($generalizedType)] = $generalizedType; // de-duplicate values - } - - $keyType = new BenevolentUnionType([new IntegerType(), new StringType()]); - if (count($itemKeyTypes) === 1) { - $keyType = array_shift($itemKeyTypes); - } - - if ($isKeysNonEmptyString) { - $keyType = TypeCombinator::intersect($keyType, new AccessoryNonEmptyStringType()); + $generalizedValueType = $itemValueType->generalize(GeneralizePrecision::moreSpecific()); + $valueTypes[$generalizedValueType->describe(VerbosityLevel::precise())] = $generalizedValueType; } - $valueTypes = TypeCombinator::union(...array_values($valueTypes)); - if ($isValuesNonEmptyString) { - $valueTypes = TypeCombinator::intersect($valueTypes, new AccessoryNonEmptyStringType()); - } + $keyType = TypeCombinator::union(...array_values($keyTypes)); + $valueType = TypeCombinator::union(...array_values($valueTypes)); - $arrayType = new ArrayType($keyType, $valueTypes); + $arrayType = new ArrayType($keyType, $valueType); if ($isList) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } - $types = []; - $types[] = $arrayType; - $types[] = new OversizedArrayType(); - if (!$isEmptyArray) { - $types[] = new NonEmptyArrayType(); - } - - return TypeCombinator::intersect(...$types); + return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType()); } /** diff --git a/src/Reflection/OversizedConstantArrayTypeException.php b/src/Reflection/OversizedConstantArrayTypeException.php deleted file mode 100644 index 8f59ca125fd..00000000000 --- a/src/Reflection/OversizedConstantArrayTypeException.php +++ /dev/null @@ -1,10 +0,0 @@ -