diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 122340cc27b..057a7f3bcbf 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -138,6 +138,7 @@ 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_MEMBER_LIMIT = 16; /** @var Type[] */ private array $resolvedTypes = []; @@ -2743,10 +2744,12 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, } if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { - $varType = TypeCombinator::intersect( - $varType, - new HasOffsetValueType($dimType, $type), - ); + if (!$this->isLargeUnionType($exprVarType)) { + $varType = TypeCombinator::intersect( + $varType, + new HasOffsetValueType($dimType, $type), + ); + } } $scope = $scope->specifyExpressionType( @@ -2795,6 +2798,15 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, return $scope; } + private function isLargeUnionType(Type $type): bool + { + if (!$type instanceof UnionType) { + return false; + } + + return count($type->getTypes()) > self::ARRAY_DIM_FETCH_UNION_MEMBER_LIMIT; + } + public function assignExpression(Expr $expr, Type $type, Type $nativeType): self { $scope = $this; diff --git a/tests/bench/data/bug-14462.php b/tests/bench/data/bug-14462.php new file mode 100644 index 00000000000..f8e40cc5466 --- /dev/null +++ b/tests/bench/data/bug-14462.php @@ -0,0 +1,48 @@ +} */ +function get_config(): array { + return ['menu' => []]; +} + +$config = get_config(); + +$data = [ ]; +if ($config['menu']['notefrais']) { + $data[] = [ 'name' => 'notefrais', 'menu' => 'notefrais_base' ]; +} +if ($config['menu']['achat']) { + $data[] = [ 'name' => 'achat', 'menu' => 'achat_base' ]; +} + +if ($config['menu']['vente-commande_planning'] || $config['menu']['vente-commande']) { + $data[] = [ 'name' => 'vente' , 'menu' => 'vente_order_recent' ]; +} +if ($config['menu']['vente-commande_planning']) { + $data[] = [ 'name' => 'vente', 'menu' => 'vente_base_planned' ]; +} +if ($config['menu']['vente-commande']) { + $data[] = [ 'name' => 'vente', 'menu' => 'vente_base_com' ]; +} +if ($config['menu']['carte']) { + $data[] = [ 'name' => 'carte', 'menu' => '' ]; +} +if ($config['menu']['crm']) { + $data[] = [ 'name' => 'crm', 'menu' => 'crm_suivi' ]; +} +if ($config['menu']['inventaire']) { + $data[] = [ 'name' => 'inventaire', 'menu' => 'inventaire_base' ]; +} + + +foreach ($data as $row) { + $stack = [ ]; + if ($row['menu'] === 'vente_order_recent') { + $stack[] = 'f'; + } + else { + $stack[] = 'g'; + } +}