Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -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_HAS_OFFSET_VALUE_TYPE_LIMIT = 16;

/** @var Type[] */
private array $resolvedTypes = [];
Expand Down Expand Up @@ -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->hasOverflowingHasOffsetValueTypes($exprVarType)) {
$varType = TypeCombinator::intersect(
$varType,
new HasOffsetValueType($dimType, $type),
);
}
}

$scope = $scope->specifyExpressionType(
Expand Down Expand Up @@ -2795,6 +2798,15 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType,
return $scope;
}

private function hasOverflowingHasOffsetValueTypes(Type $type): bool
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the method name is misleading since it only count the types from the UnionType ; we could have a big union type without HasOffsetValueType.

We could think this method will count the number of HasOffsetValueType

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I renamed hasOverflowingHasOffsetValueTypes() to isLargeUnionType() and the constant from ARRAY_DIM_FETCH_UNION_HAS_OFFSET_VALUE_TYPE_LIMIT to ARRAY_DIM_FETCH_UNION_MEMBER_LIMIT. The new names accurately reflect that the check is about the union type's member count, not specifically about HasOffsetValueType instances. Tests and static analysis both pass.

{
if (!$type instanceof UnionType) {
return false;
}

return count($type->getTypes()) > self::ARRAY_DIM_FETCH_UNION_HAS_OFFSET_VALUE_TYPE_LIMIT;
}

public function assignExpression(Expr $expr, Type $type, Type $nativeType): self
{
$scope = $this;
Expand Down
48 changes: 48 additions & 0 deletions tests/bench/data/bug-14462.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);

namespace Bug14462;

/** @return array{menu: array<non-empty-string, bool>} */
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';
}
}
Loading