Skip to content

Commit 253903a

Browse files
schlndhondrejmirtes
authored andcommitted
Fix integer range pow issues
1 parent b143449 commit 253903a

File tree

7 files changed

+105
-4
lines changed

7 files changed

+105
-4
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/Analyser/nsrt/pow.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ function (): void {
4747
$x = 4;
4848
}
4949

50-
assertType('int<4, 27>|int<16, 81>', pow($range, $x));
51-
assertType('int<4, 27>|int<16, 81>', $range ** $x);
50+
assertType('int<4, 81>', pow($range, $x));
51+
assertType('int<4, 81>', $range ** $x);
5252

53-
assertType('int<4, 27>|int<16, 64>', pow($x, $range));
54-
assertType('int<4, 27>|int<16, 64>', $x ** $range);
53+
assertType('int<4, 64>', pow($x, $range));
54+
assertType('int<4, 64>', $x ** $range);
5555

5656
assertType('int<4, 27>', pow($range, $range));
5757
assertType('int<4, 27>', $range ** $range);

tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,10 @@ public function testBug5365(): void
433433
$this->analyse([__DIR__ . '/data/bug-5365.php'], []);
434434
}
435435

436+
public function testBug8555(): void
437+
{
438+
$this->treatPhpDocTypesAsCertain = true;
439+
$this->analyse([__DIR__ . '/data/bug-8555.php'], []);
440+
}
441+
436442
}

tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ public function testBug8797(): void
146146
$this->analyse([__DIR__ . '/data/bug-8797.php'], []);
147147
}
148148

149+
public function testBug7937(): void
150+
{
151+
$this->treatPhpDocTypesAsCertain = true;
152+
$this->analyse([__DIR__ . '/data/bug-7937.php'], []);
153+
}
154+
149155
public function dataReportAlwaysTrueInLastCondition(): iterable
150156
{
151157
yield [false, [
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7937;
4+
5+
class HelloWorld
6+
{
7+
public function f(int $a, int $b)
8+
{
9+
if (!$a && !$b) {
10+
return "";
11+
}
12+
13+
$output = " ";
14+
15+
if ($a) {
16+
$output .= "$a";
17+
}
18+
19+
\PHPStan\dumpType($a);
20+
21+
if ($b) {
22+
\PHPStan\dumpType($a);
23+
24+
if (!$a) {
25+
$output .= "_";
26+
}
27+
}
28+
29+
return $output;
30+
}
31+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Bug8555;
4+
5+
/**
6+
* @return array<string, int|null>
7+
*/
8+
function test(int $first, int $second): array
9+
{
10+
return [
11+
'test' => $first && $second ? $first : null,
12+
'test2' => $first && $second ? $first : null,
13+
];
14+
}

tests/PHPStan/Type/TypeCombinatorTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,34 @@ public function dataUnion(): iterable
15601560
UnionType::class,
15611561
'int<1, 3>|int<7, 9>',
15621562
],
1563+
[
1564+
[
1565+
IntegerRangeType::fromInterval(4, 9),
1566+
IntegerRangeType::fromInterval(16, 81),
1567+
IntegerRangeType::fromInterval(8, 27),
1568+
],
1569+
IntegerRangeType::class,
1570+
'int<4, 81>',
1571+
],
1572+
[
1573+
[
1574+
IntegerRangeType::fromInterval(8, 27),
1575+
IntegerRangeType::fromInterval(4, 6),
1576+
new ConstantIntegerType(7),
1577+
IntegerRangeType::fromInterval(16, 81),
1578+
],
1579+
IntegerRangeType::class,
1580+
'int<4, 81>',
1581+
],
1582+
[
1583+
[
1584+
new IntegerType(),
1585+
IntegerRangeType::fromInterval(null, -1),
1586+
IntegerRangeType::fromInterval(1, null),
1587+
],
1588+
IntegerType::class,
1589+
'int',
1590+
],
15631591
[
15641592
[
15651593
IntegerRangeType::fromInterval(1, 3),

0 commit comments

Comments
 (0)