Skip to content

Commit

Permalink
Use Type::getFiniteTypes() for removing types
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 19, 2023
1 parent fa9a951 commit b5cf52b
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 7 deletions.
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ parameters:
count: 1
path: src/Analyser/MutatingScope.php

-
message: "#^Casting to string something that's already string\\.$#"
count: 2
path: src/Analyser/MutatingScope.php

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#"
count: 4
Expand Down
4 changes: 2 additions & 2 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -3659,7 +3659,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
}
$typeSpecifications[] = [
'sure' => true,
'exprString' => $exprString,
'exprString' => (string) $exprString,
'expr' => $expr,
'type' => $type,
];
Expand All @@ -3670,7 +3670,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
}
$typeSpecifications[] = [
'sure' => false,
'exprString' => $exprString,
'exprString' => (string) $exprString,
'expr' => $expr,
'type' => $type,
];
Expand Down
6 changes: 2 additions & 4 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ public function specifyTypesInCondition(
$exprLeftType = $scope->getType($expr->left);
$exprRightType = $scope->getType($expr->right);
if (
count($exprLeftType->getConstantScalarValues()) === 1
|| count($exprLeftType->getEnumCases()) === 1
count($exprLeftType->getFiniteTypes()) === 1
|| ($exprLeftType->isConstantValue()->yes() && !$exprRightType->equals($exprLeftType) && $exprRightType->isSuperTypeOf($exprLeftType)->yes())
) {
$types = $this->create(
Expand All @@ -239,8 +238,7 @@ public function specifyTypesInCondition(
);
}
if (
count($exprRightType->getConstantScalarValues()) === 1
|| count($exprRightType->getEnumCases()) === 1
count($exprRightType->getFiniteTypes()) === 1
|| ($exprRightType->isConstantValue()->yes() && !$exprLeftType->equals($exprRightType) && $exprLeftType->isSuperTypeOf($exprRightType)->yes())
) {
$leftType = $this->create(
Expand Down
36 changes: 35 additions & 1 deletion src/Type/TypeCombinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,41 @@ public static function remove(Type $fromType, Type $typeToRemove): Type
}
}

return $fromType->tryRemove($typeToRemove) ?? $fromType;
$removed = $fromType->tryRemove($typeToRemove);
if ($removed !== null) {
return $removed;
}

$fromFiniteTypes = $fromType->getFiniteTypes();
if (count($fromFiniteTypes) > 0) {
$finiteTypesToRemove = $typeToRemove->getFiniteTypes();
if (count($finiteTypesToRemove) === 1) {
$result = [];
foreach ($fromFiniteTypes as $finiteType) {
if ($finiteType->equals($finiteTypesToRemove[0])) {
continue;
}

$result[] = $finiteType;
}

if (count($result) === count($fromFiniteTypes)) {
return $fromType;
}

if (count($result) === 0) {
return new NeverType();
}

if (count($result) === 1) {
return $result[0];
}

return new UnionType($result);
}
}

return $fromType;
}

public static function removeNull(Type $type): Type
Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9404.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/globals.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9208.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/finite-types.php');
}

/**
Expand Down
33 changes: 33 additions & 0 deletions tests/PHPStan/Analyser/data/finite-types.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace FiniteTypes;

use function PHPStan\Testing\assertType;

class Foo
{

public function doFoo(bool $a, bool $b): void
{
$array = [$a, $b];
if ($array === [true, false]) {
assertType('array{true, false}', $array);
return;
}

assertType('array{false, false}|array{false, true}|array{true, true}', $array);
if ($array === [false, false]) {
assertType('array{false, false}', $array);
return;
}

assertType('array{bool, true}', $array);
if ($array === [true, true]) {
assertType('array{true, true}', $array);
return;
}

assertType('array{false, true}', $array);
}

}

0 comments on commit b5cf52b

Please sign in to comment.