Skip to content

Commit 973fe50

Browse files
jlherrenondrejmirtes
authored andcommitted
Improve comparison operators
In particular, this fixes wrong comparisions like: * -1 < null being treated as always true * 1.9 > 1 being treated as always false
1 parent 456f443 commit 973fe50

36 files changed

Lines changed: 296 additions & 38 deletions

src/Analyser/MutatingScope.php

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -524,46 +524,20 @@ private function resolveType(Expr $node): Type
524524
return new NeverType(true);
525525
}
526526

527-
if (
528-
$node instanceof Expr\BinaryOp\Greater
529-
|| $node instanceof Expr\BinaryOp\GreaterOrEqual
530-
|| $node instanceof Expr\BinaryOp\Smaller
531-
|| $node instanceof Expr\BinaryOp\SmallerOrEqual
532-
) {
533-
$leftType = $this->getType($node->left);
534-
$rightType = $this->getType($node->right);
535-
536-
if ($rightType instanceof ConstantIntegerType) {
537-
$rightValue = $rightType->getValue();
538-
539-
if ($node instanceof Expr\BinaryOp\Greater) {
540-
$rightIntervalType = IntegerRangeType::fromInterval($rightValue + 1, null);
541-
} elseif ($node instanceof Expr\BinaryOp\GreaterOrEqual) {
542-
$rightIntervalType = IntegerRangeType::fromInterval($rightValue, null);
543-
} elseif ($node instanceof Expr\BinaryOp\Smaller) {
544-
$rightIntervalType = IntegerRangeType::fromInterval(null, $rightValue - 1);
545-
} else {
546-
$rightIntervalType = IntegerRangeType::fromInterval(null, $rightValue);
547-
}
548-
549-
return $rightIntervalType->isSuperTypeOf($leftType->toInteger())->toBooleanType();
550-
} elseif ($leftType instanceof ConstantIntegerType) {
551-
$leftValue = $leftType->getValue();
527+
if ($node instanceof Expr\BinaryOp\Smaller) {
528+
return $this->getType($node->left)->isSmallerThan($this->getType($node->right))->toBooleanType();
529+
}
552530

553-
if ($node instanceof Expr\BinaryOp\Smaller) {
554-
$leftIntervalType = IntegerRangeType::fromInterval($leftValue + 1, null);
555-
} elseif ($node instanceof Expr\BinaryOp\SmallerOrEqual) {
556-
$leftIntervalType = IntegerRangeType::fromInterval($leftValue, null);
557-
} elseif ($node instanceof Expr\BinaryOp\Greater) {
558-
$leftIntervalType = IntegerRangeType::fromInterval(null, $leftValue - 1);
559-
} else {
560-
$leftIntervalType = IntegerRangeType::fromInterval(null, $leftValue);
561-
}
531+
if ($node instanceof Expr\BinaryOp\SmallerOrEqual) {
532+
return $this->getType($node->left)->isSmallerThan($this->getType($node->right), true)->toBooleanType();
533+
}
562534

563-
return $leftIntervalType->isSuperTypeOf($rightType->toInteger())->toBooleanType();
564-
}
535+
if ($node instanceof Expr\BinaryOp\Greater) {
536+
return $this->getType($node->right)->isSmallerThan($this->getType($node->left))->toBooleanType();
537+
}
565538

566-
return new BooleanType();
539+
if ($node instanceof Expr\BinaryOp\GreaterOrEqual) {
540+
return $this->getType($node->right)->isSmallerThan($this->getType($node->left), true)->toBooleanType();
567541
}
568542

569543
if (

src/Type/Accessory/AccessoryNumericStringType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHPStan\Type\Traits\NonIterableTypeTrait;
1818
use PHPStan\Type\Traits\NonObjectTypeTrait;
1919
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
20+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
2021
use PHPStan\Type\Type;
2122
use PHPStan\Type\UnionType;
2223

@@ -27,6 +28,7 @@ class AccessoryNumericStringType implements CompoundType, AccessoryType
2728
use NonObjectTypeTrait;
2829
use NonIterableTypeTrait;
2930
use UndecidedBooleanTypeTrait;
31+
use UndecidedComparisonCompoundTypeTrait;
3032
use NonGenericTypeTrait;
3133

3234
public function getReferencedClasses(): array

src/Type/Accessory/HasMethodType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPStan\Type\IntersectionType;
1212
use PHPStan\Type\Traits\NonGenericTypeTrait;
1313
use PHPStan\Type\Traits\ObjectTypeTrait;
14+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
1415
use PHPStan\Type\Type;
1516
use PHPStan\Type\UnionType;
1617

@@ -19,6 +20,7 @@ class HasMethodType implements AccessoryType, CompoundType
1920

2021
use ObjectTypeTrait;
2122
use NonGenericTypeTrait;
23+
use UndecidedComparisonCompoundTypeTrait;
2224

2325
private string $methodName;
2426

src/Type/Accessory/HasOffsetType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
1515
use PHPStan\Type\Traits\NonGenericTypeTrait;
1616
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
17+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
1718
use PHPStan\Type\Type;
1819
use PHPStan\Type\UnionType;
1920

@@ -25,6 +26,7 @@ class HasOffsetType implements CompoundType, AccessoryType
2526
use MaybeObjectTypeTrait;
2627
use TruthyBooleanTypeTrait;
2728
use NonGenericTypeTrait;
29+
use UndecidedComparisonCompoundTypeTrait;
2830

2931
private \PHPStan\Type\Type $offsetType;
3032

src/Type/Accessory/HasPropertyType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\Type\IntersectionType;
1010
use PHPStan\Type\Traits\NonGenericTypeTrait;
1111
use PHPStan\Type\Traits\ObjectTypeTrait;
12+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
1213
use PHPStan\Type\Type;
1314
use PHPStan\Type\UnionType;
1415

@@ -17,6 +18,7 @@ class HasPropertyType implements AccessoryType, CompoundType
1718

1819
use ObjectTypeTrait;
1920
use NonGenericTypeTrait;
21+
use UndecidedComparisonCompoundTypeTrait;
2022

2123
private string $propertyName;
2224

src/Type/Accessory/NonEmptyArrayType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\Traits\NonGenericTypeTrait;
1313
use PHPStan\Type\Traits\NonObjectTypeTrait;
1414
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
15+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
1516
use PHPStan\Type\Type;
1617
use PHPStan\Type\UnionType;
1718

@@ -22,6 +23,7 @@ class NonEmptyArrayType implements CompoundType, AccessoryType
2223
use NonObjectTypeTrait;
2324
use TruthyBooleanTypeTrait;
2425
use NonGenericTypeTrait;
26+
use UndecidedComparisonCompoundTypeTrait;
2527

2628
public function getReferencedClasses(): array
2729
{

src/Type/ArrayType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
use PHPStan\Type\Traits\MaybeCallableTypeTrait;
1717
use PHPStan\Type\Traits\NonObjectTypeTrait;
1818
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
19+
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
1920

2021
class ArrayType implements Type
2122
{
2223

2324
use MaybeCallableTypeTrait;
2425
use NonObjectTypeTrait;
2526
use UndecidedBooleanTypeTrait;
27+
use UndecidedComparisonTypeTrait;
2628

2729
private \PHPStan\Type\Type $keyType;
2830

src/Type/BooleanType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\Traits\NonIterableTypeTrait;
1313
use PHPStan\Type\Traits\NonObjectTypeTrait;
1414
use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
15+
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
1516

1617
class BooleanType implements Type
1718
{
@@ -21,6 +22,7 @@ class BooleanType implements Type
2122
use NonIterableTypeTrait;
2223
use NonObjectTypeTrait;
2324
use UndecidedBooleanTypeTrait;
25+
use UndecidedComparisonTypeTrait;
2426
use NonGenericTypeTrait;
2527

2628
public function describe(VerbosityLevel $level): string

src/Type/CallableType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHPStan\Type\Traits\MaybeObjectTypeTrait;
1414
use PHPStan\Type\Traits\MaybeOffsetAccessibleTypeTrait;
1515
use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
16+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
1617

1718
class CallableType implements CompoundType, ParametersAcceptor
1819
{
@@ -21,6 +22,7 @@ class CallableType implements CompoundType, ParametersAcceptor
2122
use MaybeObjectTypeTrait;
2223
use MaybeOffsetAccessibleTypeTrait;
2324
use TruthyBooleanTypeTrait;
25+
use UndecidedComparisonCompoundTypeTrait;
2426

2527
/** @var array<int, \PHPStan\Reflection\ParameterReflection> */
2628
private array $parameters;

src/Type/ClosureType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
use PHPStan\Type\Constant\ConstantIntegerType;
1818
use PHPStan\Type\Generic\TemplateTypeMap;
1919
use PHPStan\Type\Traits\NonGenericTypeTrait;
20+
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
2021

2122
class ClosureType implements TypeWithClassName, ParametersAcceptor
2223
{
2324

2425
use NonGenericTypeTrait;
26+
use UndecidedComparisonTypeTrait;
2527

2628
private ObjectType $objectType;
2729

0 commit comments

Comments
 (0)