Skip to content

Commit 0c8fd6a

Browse files
committed
improve EnumCaseObjectType subtracting
1 parent f0762db commit 0c8fd6a

File tree

5 files changed

+35
-23
lines changed

5 files changed

+35
-23
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,12 +1692,6 @@ parameters:
16921692
count: 5
16931693
path: src/Type/TypeCombinator.php
16941694

1695-
-
1696-
message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#'
1697-
identifier: phpstanApi.instanceofType
1698-
count: 2
1699-
path: src/Type/TypeCombinator.php
1700-
17011695
-
17021696
message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#'
17031697
identifier: phpstanApi.instanceofType

src/Type/Enum/EnumCaseObjectType.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\Type\Constant\ConstantStringType;
1919
use PHPStan\Type\GeneralizePrecision;
2020
use PHPStan\Type\IsSuperTypeOfResult;
21+
use PHPStan\Type\NeverType;
2122
use PHPStan\Type\ObjectType;
2223
use PHPStan\Type\SubtractableType;
2324
use PHPStan\Type\Type;
@@ -94,7 +95,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
9495

9596
public function subtract(Type $type): Type
9697
{
97-
return $this;
98+
return $this->changeSubtractedType($type);
9899
}
99100

100101
public function getTypeWithoutSubtractedType(): Type
@@ -104,7 +105,11 @@ public function getTypeWithoutSubtractedType(): Type
104105

105106
public function changeSubtractedType(?Type $subtractedType): Type
106107
{
107-
return $this;
108+
if ($subtractedType === null || ! $this->equals($subtractedType)) {
109+
return $this;
110+
}
111+
112+
return new NeverType();
108113
}
109114

110115
public function getSubtractedType(): ?Type

src/Type/TypeCombinator.php

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use PHPStan\Type\Constant\ConstantFloatType;
1919
use PHPStan\Type\Constant\ConstantIntegerType;
2020
use PHPStan\Type\Constant\ConstantStringType;
21-
use PHPStan\Type\Enum\EnumCaseObjectType;
2221
use PHPStan\Type\Generic\GenericClassStringType;
2322
use PHPStan\Type\Generic\TemplateArrayType;
2423
use PHPStan\Type\Generic\TemplateBenevolentUnionType;
@@ -540,7 +539,7 @@ private static function unionWithSubtractedType(
540539
return $type;
541540
}
542541

543-
if ($type instanceof SubtractableType && ! $type instanceof EnumCaseObjectType) {
542+
if ($type instanceof SubtractableType) {
544543
$subtractedType = $type->getSubtractedType() === null
545544
? $subtractedType
546545
: self::union($type->getSubtractedType(), $subtractedType);
@@ -596,17 +595,31 @@ private static function intersectWithSubtractedType(
596595
}
597596

598597
$subtractedType = self::union(...$subtractedTypes);
599-
} elseif ($b instanceof SubtractableType && ! $b instanceof EnumCaseObjectType) {
600-
$subtractedType = $b->getSubtractedType();
601-
if ($subtractedType === null) {
602-
return $a->getTypeWithoutSubtractedType();
603-
}
604598
} else {
605-
$subtractedTypeTmp = self::intersect($a->getTypeWithoutSubtractedType(), $a->getSubtractedType());
606-
if ($b->isSuperTypeOf($subtractedTypeTmp)->yes()) {
607-
return $a->getTypeWithoutSubtractedType();
599+
$isBAlreadySubtracted = $a->getSubtractedType()->isSuperTypeOf($b);
600+
601+
if ($isBAlreadySubtracted->no()) {
602+
return $a;
603+
} elseif ($isBAlreadySubtracted->yes()) {
604+
$subtractedType = self::remove($a->getSubtractedType(), $b);
605+
606+
if ($subtractedType instanceof NeverType) {
607+
$subtractedType = null;
608+
}
609+
610+
return $a->changeSubtractedType($subtractedType);
611+
} elseif ($b instanceof SubtractableType) {
612+
$subtractedType = $b->getSubtractedType();
613+
if ($subtractedType === null) {
614+
return $a->getTypeWithoutSubtractedType();
615+
}
616+
} else {
617+
$subtractedTypeTmp = self::intersect($a->getTypeWithoutSubtractedType(), $a->getSubtractedType());
618+
if ($b->isSuperTypeOf($subtractedTypeTmp)->yes()) {
619+
return $a->getTypeWithoutSubtractedType();
620+
}
621+
$subtractedType = new MixedType(false, $b);
608622
}
609-
$subtractedType = new MixedType(false, $b);
610623
}
611624

612625
$subtractedType = self::intersect(

tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8105,11 +8105,11 @@ public function dataArrayKeysInBranches(): array
81058105
'$array',
81068106
],
81078107
[
8108-
'non-empty-array&hasOffsetValue(\'key\', mixed)',
8108+
'non-empty-array&hasOffsetValue(\'key\', mixed~null)',
81098109
'$generalArray',
81108110
],
81118111
[
8112-
'mixed',
8112+
'mixed~null',
81138113
'$generalArray[\'key\']',
81148114
],
81158115
[

tests/PHPStan/Type/TypeCombinatorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ public function dataUnion(): iterable
10691069
new ObjectWithoutClassType(new ObjectType('A')),
10701070
],
10711071
MixedType::class,
1072-
'mixed=implicit',
1072+
'mixed~int=implicit',
10731073
],
10741074
[
10751075
[
@@ -1125,7 +1125,7 @@ public function dataUnion(): iterable
11251125
new ObjectType('InvalidArgumentException'),
11261126
],
11271127
MixedType::class,
1128-
'mixed=implicit', // should be MixedType~Exception+InvalidArgumentException
1128+
'mixed~Exception~InvalidArgumentException=implicit',
11291129
],
11301130
[
11311131
[

0 commit comments

Comments
 (0)