Skip to content

Commit

Permalink
Merge pull request #8934 from theodorejb/fix-loop-int-range
Browse files Browse the repository at this point in the history
Allow conditions inside loops to preserve or narrow int range
  • Loading branch information
orklah committed Dec 18, 2022
2 parents 156c108 + 0f4db69 commit 96cb44b
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 34 deletions.
2 changes: 0 additions & 2 deletions src/Psalm/Internal/Diff/FileDiffer.php
Expand Up @@ -77,8 +77,6 @@ private static function extractDiff(array $trace, int $x, int $y, array $a, arra
{
$result = [];
for ($d = count($trace) - 1; $d >= 0; --$d) {
// Todo: fix integer ranges in fors
/** @var int<0, max> $d */
$v = $trace[$d];
$k = $x - $y;

Expand Down
4 changes: 0 additions & 4 deletions src/Psalm/Internal/Type/Comparator/ArrayTypeComparator.php
Expand Up @@ -123,10 +123,6 @@ public static function isContainedBy(
}

foreach ($input_type_part->type_params as $i => $input_param) {
if ($i > 1) {
break;
}

$container_param = $container_type_part->type_params[$i];

if ($i === 0
Expand Down
8 changes: 0 additions & 8 deletions src/Psalm/Internal/Type/SimpleAssertionReconciler.php
Expand Up @@ -1962,10 +1962,6 @@ private static function reconcileIsGreaterThan(
}

foreach ($existing_var_type->getAtomicTypes() as $atomic_type) {
if ($inside_loop) {
continue;
}

if ($atomic_type instanceof TIntRange) {
if ($atomic_type->contains($assertion_value)) {
// if the range contains the assertion, the range must be adapted
Expand Down Expand Up @@ -2075,10 +2071,6 @@ private static function reconcileIsLessThan(
}

foreach ($existing_var_type->getAtomicTypes() as $atomic_type) {
if ($inside_loop) {
continue;
}

if ($atomic_type instanceof TIntRange) {
if ($atomic_type->contains($assertion_value)) {
// if the range contains the assertion, the range must be adapted
Expand Down
8 changes: 0 additions & 8 deletions src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php
Expand Up @@ -1840,10 +1840,6 @@ private static function reconcileIsLessThanOrEqualTo(
}

foreach ($existing_var_type->getAtomicTypes() as $atomic_type) {
if ($inside_loop) {
continue;
}

if ($atomic_type instanceof TIntRange) {
if ($atomic_type->contains($assertion_value)) {
// if the range contains the assertion, the range must be adapted
Expand Down Expand Up @@ -1951,10 +1947,6 @@ private static function reconcileIsGreaterThanOrEqualTo(
}

foreach ($existing_var_type->getAtomicTypes() as $atomic_type) {
if ($inside_loop) {
continue;
}

if ($atomic_type instanceof TIntRange) {
if ($atomic_type->contains($assertion_value)) {
// if the range contains the assertion, the range must be adapted
Expand Down
44 changes: 32 additions & 12 deletions tests/IntRangeTest.php
Expand Up @@ -443,9 +443,8 @@ function getInt()
'$remainder===' => 'int<min, 1>',
],
],
'SKIPPED-IntRangeRestrictWhenUntouched' => [
'IntRangeRestrictWhenUntouched' => [
'code' => '<?php
//skipped, int range in loops not supported yet
foreach ([1, 2, 3] as $i) {
if ($i > 1) {
takesInt($i);
Expand All @@ -457,34 +456,55 @@ function takesInt(int $i): void{
return;
}',
],
'SKIPPED-wrongLoopAssertion' => [
'intRangeExpandedByLoop' => [
'code' => '<?php
for ($i = 0; $i < 10; $i++) {
takesInt($i);
}
for (; $i < 20; $i++) {
takesInt($i);
}
/** @psalm-param int<0, 20> $i */
function takesInt(int $i): void{
return;
}',
],
'statementsInLoopPreserveNonNegativeIntRange' => [
'code' => '<?php
$sum = 0;
foreach ([-6, 0, 2] as $i) {
if ($i > 0) {
$sum += $i;
}
}
takesNonNegativeInt($sum);
/** @psalm-param int<0, max> $i */
function takesNonNegativeInt(int $i): void{
return;
}',
],
'wrongLoopAssertion' => [
'code' => '<?php
//skipped, int range in loops not supported yet
function a(): array {
$type_tokens = getArray();
for ($i = 0, $l = rand(0,100); $i < $l; ++$i) {
/** @psalm-trace $i */;
if ($i > 0 && rand(0,1)) {
continue;
}
/** @psalm-trace $i */;
$type_tokens[$i] = "";
/** @psalm-trace $type_tokens */;
if($i > 1){
if ($i > 1) {
$type_tokens[$i - 2];
}
}
return [];
}
/** @return array<int, string> */
function getArray(): array {
return [];
Expand Down

0 comments on commit 96cb44b

Please sign in to comment.