Skip to content

Commit b5cf52b

Browse files
committed
Use Type::getFiniteTypes() for removing types
1 parent fa9a951 commit b5cf52b

File tree

6 files changed

+78
-7
lines changed

6 files changed

+78
-7
lines changed

phpstan-baseline.neon

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ parameters:
3131
count: 1
3232
path: src/Analyser/MutatingScope.php
3333

34+
-
35+
message: "#^Casting to string something that's already string\\.$#"
36+
count: 2
37+
path: src/Analyser/MutatingScope.php
38+
3439
-
3540
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#"
3641
count: 4

src/Analyser/MutatingScope.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -3659,7 +3659,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
36593659
}
36603660
$typeSpecifications[] = [
36613661
'sure' => true,
3662-
'exprString' => $exprString,
3662+
'exprString' => (string) $exprString,
36633663
'expr' => $expr,
36643664
'type' => $type,
36653665
];
@@ -3670,7 +3670,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
36703670
}
36713671
$typeSpecifications[] = [
36723672
'sure' => false,
3673-
'exprString' => $exprString,
3673+
'exprString' => (string) $exprString,
36743674
'expr' => $expr,
36753675
'type' => $type,
36763676
];

src/Analyser/TypeSpecifier.php

+2-4
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,7 @@ public function specifyTypesInCondition(
225225
$exprLeftType = $scope->getType($expr->left);
226226
$exprRightType = $scope->getType($expr->right);
227227
if (
228-
count($exprLeftType->getConstantScalarValues()) === 1
229-
|| count($exprLeftType->getEnumCases()) === 1
228+
count($exprLeftType->getFiniteTypes()) === 1
230229
|| ($exprLeftType->isConstantValue()->yes() && !$exprRightType->equals($exprLeftType) && $exprRightType->isSuperTypeOf($exprLeftType)->yes())
231230
) {
232231
$types = $this->create(
@@ -239,8 +238,7 @@ public function specifyTypesInCondition(
239238
);
240239
}
241240
if (
242-
count($exprRightType->getConstantScalarValues()) === 1
243-
|| count($exprRightType->getEnumCases()) === 1
241+
count($exprRightType->getFiniteTypes()) === 1
244242
|| ($exprRightType->isConstantValue()->yes() && !$exprLeftType->equals($exprRightType) && $exprLeftType->isSuperTypeOf($exprRightType)->yes())
245243
) {
246244
$leftType = $this->create(

src/Type/TypeCombinator.php

+35-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,41 @@ public static function remove(Type $fromType, Type $typeToRemove): Type
7474
}
7575
}
7676

77-
return $fromType->tryRemove($typeToRemove) ?? $fromType;
77+
$removed = $fromType->tryRemove($typeToRemove);
78+
if ($removed !== null) {
79+
return $removed;
80+
}
81+
82+
$fromFiniteTypes = $fromType->getFiniteTypes();
83+
if (count($fromFiniteTypes) > 0) {
84+
$finiteTypesToRemove = $typeToRemove->getFiniteTypes();
85+
if (count($finiteTypesToRemove) === 1) {
86+
$result = [];
87+
foreach ($fromFiniteTypes as $finiteType) {
88+
if ($finiteType->equals($finiteTypesToRemove[0])) {
89+
continue;
90+
}
91+
92+
$result[] = $finiteType;
93+
}
94+
95+
if (count($result) === count($fromFiniteTypes)) {
96+
return $fromType;
97+
}
98+
99+
if (count($result) === 0) {
100+
return new NeverType();
101+
}
102+
103+
if (count($result) === 1) {
104+
return $result[0];
105+
}
106+
107+
return new UnionType($result);
108+
}
109+
}
110+
111+
return $fromType;
78112
}
79113

80114
public static function removeNull(Type $type): Type

tests/PHPStan/Analyser/NodeScopeResolverTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,7 @@ public function dataFileAsserts(): iterable
12611261
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9404.php');
12621262
yield from $this->gatherAssertTypes(__DIR__ . '/data/globals.php');
12631263
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9208.php');
1264+
yield from $this->gatherAssertTypes(__DIR__ . '/data/finite-types.php');
12641265
}
12651266

12661267
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace FiniteTypes;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function doFoo(bool $a, bool $b): void
11+
{
12+
$array = [$a, $b];
13+
if ($array === [true, false]) {
14+
assertType('array{true, false}', $array);
15+
return;
16+
}
17+
18+
assertType('array{false, false}|array{false, true}|array{true, true}', $array);
19+
if ($array === [false, false]) {
20+
assertType('array{false, false}', $array);
21+
return;
22+
}
23+
24+
assertType('array{bool, true}', $array);
25+
if ($array === [true, true]) {
26+
assertType('array{true, true}', $array);
27+
return;
28+
}
29+
30+
assertType('array{false, true}', $array);
31+
}
32+
33+
}

0 commit comments

Comments
 (0)