diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index e60242af43..c181393494 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -139,6 +139,8 @@ class MutatingScope implements Scope, NodeCallbackInvoker public const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid'; private const CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME = 'containsSuperGlobal'; + private const ARRAY_DIM_FETCH_UNION_HAS_OFFSET_VALUE_TYPE_LIMIT = 16; + /** @var Type[] */ private array $resolvedTypes = []; @@ -2689,6 +2691,8 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, $exprVarType = $scope->getType($expr->var); $isArray = $exprVarType->isArray(); if (!$exprVarType instanceof MixedType && !$isArray->no()) { + $tooManyHasOffsetValueTypes = false; + $varType = $exprVarType; if (!$isArray->yes()) { if ($dimType->isInteger()->yes()) { @@ -2696,9 +2700,30 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, } else { $varType = TypeCombinator::intersect($exprVarType, StaticTypeFactory::generalOffsetAccessibleType()); } + + if ($exprVarType instanceof UnionType) { + $hasOffsetAccessoryCount = 0; + foreach ($exprVarType->getTypes() as $innerType) { + foreach (TypeUtils::getAccessoryTypes($innerType) as $accessoryType) { + if (!($accessoryType instanceof HasOffsetValueType)) { + continue; + } + + $hasOffsetAccessoryCount++; + + if ($hasOffsetAccessoryCount > self::ARRAY_DIM_FETCH_UNION_HAS_OFFSET_VALUE_TYPE_LIMIT) { + $tooManyHasOffsetValueTypes = true; + break 2; + } + } + } + } } - if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { + if ( + !$tooManyHasOffsetValueTypes + && ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) + ) { $varType = TypeCombinator::intersect( $varType, new HasOffsetValueType($dimType, $type), diff --git a/tests/PHPStan/Analyser/nsrt/bug-14319.php b/tests/PHPStan/Analyser/nsrt/bug-14319.php new file mode 100644 index 0000000000..395d47d78f --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14319.php @@ -0,0 +1,49 @@ +