Skip to content

Commit 81b7706

Browse files
committed
fix union of int ranges
1 parent 873450c commit 81b7706

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src/Type/TypeCombinator.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
use function md5;
3838
use function sprintf;
3939
use function usort;
40+
use const PHP_INT_MAX;
41+
use const PHP_INT_MIN;
4042

4143
/**
4244
* @api
@@ -185,6 +187,7 @@ public static function union(Type ...$types): Type
185187
$scalarTypes = [];
186188
$hasGenericScalarTypes = [];
187189
$enumCaseTypes = [];
190+
$integerRangeTypes = [];
188191
for ($i = 0; $i < $typesCount; $i++) {
189192
if ($types[$i] instanceof ConstantScalarType) {
190193
$type = $types[$i];
@@ -212,6 +215,13 @@ public static function union(Type ...$types): Type
212215
continue;
213216
}
214217

218+
if ($types[$i] instanceof IntegerRangeType) {
219+
$integerRangeTypes[] = $types[$i];
220+
unset($types[$i]);
221+
222+
continue;
223+
}
224+
215225
if (!$types[$i]->isArray()->yes()) {
216226
continue;
217227
}
@@ -225,6 +235,12 @@ public static function union(Type ...$types): Type
225235
}
226236

227237
$enumCaseTypes = array_values($enumCaseTypes);
238+
usort(
239+
$integerRangeTypes,
240+
static fn (IntegerRangeType $a, IntegerRangeType $b): int => ($a->getMin() ?? PHP_INT_MIN) <=> ($b->getMin() ?? PHP_INT_MIN)
241+
?: ($a->getMax() ?? PHP_INT_MAX) <=> ($b->getMax() ?? PHP_INT_MAX)
242+
);
243+
$types = array_merge($types, $integerRangeTypes);
228244
$types = array_values($types);
229245
$typesCount = count($types);
230246

tests/PHPStan/Type/TypeCombinatorTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,25 @@ public function dataUnion(): iterable
15581558
UnionType::class,
15591559
'int<1, 3>|int<7, 9>',
15601560
],
1561+
[
1562+
[
1563+
IntegerRangeType::fromInterval(4, 9),
1564+
IntegerRangeType::fromInterval(16, 81),
1565+
IntegerRangeType::fromInterval(8, 27),
1566+
],
1567+
IntegerRangeType::class,
1568+
'int<4, 81>',
1569+
],
1570+
[
1571+
[
1572+
IntegerRangeType::fromInterval(8, 27),
1573+
IntegerRangeType::fromInterval(4, 6),
1574+
new ConstantIntegerType(7),
1575+
IntegerRangeType::fromInterval(16, 81),
1576+
],
1577+
IntegerRangeType::class,
1578+
'int<4, 81>',
1579+
],
15611580
[
15621581
[
15631582
IntegerRangeType::fromInterval(1, 3),

0 commit comments

Comments
 (0)