Skip to content

Commit

Permalink
Intersect optimization for large unions
Browse files Browse the repository at this point in the history
  • Loading branch information
neclimdul committed Jun 24, 2022
1 parent 4a880d1 commit f26cff0
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 7 deletions.
5 changes: 2 additions & 3 deletions src/Analyser/TypeSpecifier.php
Expand Up @@ -342,9 +342,8 @@ public function specifyTypesInCondition(
}

if ($context->true()) {
$type = TypeCombinator::intersect($scope->getType($expr->right), $scope->getType($expr->left));
$leftTypes = $this->create($expr->left, $type, $context, false, $scope, $rootExpr);
$rightTypes = $this->create($expr->right, $type, $context, false, $scope, $rootExpr);
$leftTypes = $this->create($expr->left, $exprRightType, $context, false, $scope, $rootExpr);
$rightTypes = $this->create($expr->right, $exprLeftType, $context, false, $scope, $rootExpr);
return $leftTypes->unionWith($rightTypes);
} elseif ($context->false()) {
return $this->create($expr->left, $exprLeftType, $context, false, $scope, $rootExpr)->normalize($scope)
Expand Down
6 changes: 4 additions & 2 deletions src/Type/TypeCombinator.php
Expand Up @@ -638,11 +638,13 @@ public static function intersect(Type ...$types): Type
$topLevelUnionSubTypes = [];
$innerTypes = $type->getTypes();
usort($innerTypes, $sortTypes);
$slice1 = array_slice($types, 0, $i);
$slice2 = array_slice($types, $i + 1);
foreach ($innerTypes as $innerUnionSubType) {
$topLevelUnionSubTypes[] = self::intersect(
$innerUnionSubType,
...array_slice($types, 0, $i),
...array_slice($types, $i + 1),
...$slice1,
...$slice2,
);
}

Expand Down
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/TypeSpecifierTest.php
Expand Up @@ -422,7 +422,7 @@ public function dataCondition(): array
new Variable('foo'),
new Variable('bar'),
),
['$foo' => 'Bar', '$bar' => 'Bar'],
['$foo' => 'Bar', '$bar' => 'mixed'], // could be '$bar' => 'Bar'
[],
],
[
Expand Down Expand Up @@ -1067,7 +1067,7 @@ public function dataCondition(): array
),
[
'$foo' => 'array<string, mixed>',
'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array<string, mixed>',
'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array', // could be 'array<string, mixed>'
],
[],
],
Expand Down

0 comments on commit f26cff0

Please sign in to comment.