1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Better reconciling of ++/-- operators in ints

This commit is contained in:
robchett 2023-10-08 20:29:28 +01:00 committed by Robert Chettleburgh
parent d925bf5226
commit 8414d70a77
2 changed files with 80 additions and 6 deletions

View File

@ -823,12 +823,28 @@ final class ArithmeticOpAnalyzer
$result_type = Type::getInt();
}
}
} elseif ($parent instanceof VirtualPlus) {
$start = $left_type_part instanceof TLiteralInt ? $left_type_part->value : 1;
$result_type = Type::combineUnionTypes(Type::getIntRange($start, null), $result_type);
} elseif ($parent instanceof VirtualMinus) {
$start = $left_type_part instanceof TLiteralInt ? $left_type_part->value : 1;
$result_type = Type::combineUnionTypes(Type::getIntRange(null, $start), $result_type);
} elseif ($parent instanceof VirtualPlus || $parent instanceof VirtualMinus) {
$sum = $parent instanceof VirtualPlus ? 1 : -1;
if ($context && $context->inside_loop && $left_type_part instanceof TLiteralInt) {
if ($parent instanceof VirtualPlus) {
$new_type = new TIntRange($left_type_part->value + $sum, null);
} else {
$new_type = new TIntRange(null, $left_type_part->value + $sum);
}
} elseif ($left_type_part instanceof TLiteralInt) {
$new_type = new TLiteralInt($left_type_part->value + $sum);
} elseif ($left_type_part instanceof TIntRange) {
$start = $left_type_part->min_bound === null ? null : $left_type_part->min_bound + $sum;
$end = $left_type_part->max_bound === null ? null : $left_type_part->max_bound + $sum;
$new_type = new TIntRange($start, $end);
} else {
$new_type = new TInt();
}
$result_type = Type::combineUnionTypes(
new Union([$new_type], ['from_calculation' => true]),
$result_type,
);
} else {
$result_type = Type::combineUnionTypes(
$always_positive ? Type::getIntRange(1, null) : Type::getInt(true),

View File

@ -441,6 +441,64 @@ class RedundantConditionTest extends TestCase
}
}',
],
'allowIntValueCheckAfterComparisonDueToUnderflow' => [
'code' => '<?php
function foo(int $x) : void {
$x = $x - 1;
if (!is_int($x)) {
echo "Is a float.";
} else {
echo "Is an int.";
}
}
function bar(int $x) : void {
$x = $x - 1;
if (is_float($x)) {
echo "Is a float.";
} else {
echo "Is an int.";
}
}',
],
'allowIntValueCheckAfterComparisonDueToUnderflowDec' => [
'code' => '<?php
function foo(int $x) : void {
$x--;
if (!is_int($x)) {
echo "Is a float.";
} else {
echo "Is an int.";
}
}
function bar(int $x) : void {
$x--;
if (is_float($x)) {
echo "Is a float.";
} else {
echo "Is an int.";
}
}',
],
'allowIntValueCheckAfterComparisonDueToConditionalUnderflow' => [
'code' => '<?php
function foo(int $x) : void {
if (rand(0, 1)) {
$x = $x - 1;
}
if (is_float($x)) {
echo "Is a float.";
} else {
echo "Is an int.";
}
}',
],
'changeStringValue' => [
'code' => '<?php
$concat = "";