Skip to content

Commit

Permalink
Improve loose comparison on constant types
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Dec 25, 2024
1 parent 9f78100 commit 702b082
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/Type/Constant/ConstantArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,18 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult

public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
{
if ($this->isIterableAtLeastOnce()->no() && count($type->getConstantScalarValues()) === 1) {
// @phpstan-ignore equal.invalid, equal.notAllowed
return new ConstantBooleanType($type->getConstantScalarValues()[0] == []); // phpcs:ignore
if ($type->isInteger()->yes()) {
return new ConstantBooleanType(false);
}

if ($this->isIterableAtLeastOnce()->no()) {
if (count($type->getConstantScalarValues()) === 1) {
// @phpstan-ignore equal.invalid, equal.notAllowed
return new ConstantBooleanType($type->getConstantScalarValues()[0] == []); // phpcs:ignore
}
if ($type->isIterableAtLeastOnce()->yes()) {
return new ConstantBooleanType(false);
}
}

return new BooleanType();
Expand Down
28 changes: 27 additions & 1 deletion tests/PHPStan/Analyser/nsrt/loose-comparisons.php
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,8 @@ public function sayInt(
array $array,
int $int,
int $intRange,
string $emptyStr,
string $phpStr,
): void
{
assertType('bool', $int == $true);
Expand All @@ -651,6 +653,20 @@ public function sayInt(
assertType('false', $intRange == $emptyArr);
assertType('false', $intRange == $array);

assertType('false', 5 == $emptyArr);
assertType('false', $emptyArr == 5);
assertType('false', 5 == $array);
assertType('false', $array == 5);
assertType('false', [] == 5);
assertType('false', 5 == []);

assertType('false', 5 == $emptyStr);
assertType('false', 5 == $phpStr);
assertType('false', 5 == 'a');

assertType('false', $emptyStr == 5);
assertType('false', $phpStr == 5);
assertType('false', 'a' == 5);
}

/**
Expand Down Expand Up @@ -703,6 +719,7 @@ public function sayConstUnion(
* @param lowercase-string $lower
* @param array{} $emptyArr
* @param non-empty-array $nonEmptyArr
* @param array{abc: string, num?: int, nullable: ?string} $arrShape
* @param int<10, 20> $intRange
*/
public function sayIntersection(
Expand All @@ -712,6 +729,7 @@ public function sayIntersection(
array $emptyArr,
array $nonEmptyArr,
array $arr,
array $arrShape,
int $i,
int $intRange,
): void
Expand Down Expand Up @@ -743,10 +761,18 @@ public function sayIntersection(
assertType('false', $nonEmptyArr == $i);
assertType('false', $arr == $intRange);
assertType('false', $nonEmptyArr == $intRange);
assertType('bool', $emptyArr == $nonEmptyArr); // should be false
assertType('false', $emptyArr == $nonEmptyArr);
assertType('false', $nonEmptyArr == $emptyArr);
assertType('bool', $arr == $nonEmptyArr);
assertType('bool', $nonEmptyArr == $arr);
assertType('false', 5 == $arr);
assertType('false', $arr == 5);
assertType('false', 5 == $emptyArr);
assertType('false', $emptyArr == 5);
assertType('false', 5 == $nonEmptyArr);
assertType('false', $nonEmptyArr == 5);
assertType('false', 5 == $arrShape);
assertType('false', $arrShape == 5);

assertType('bool', '' == $lower);
if ($lower != '') {
Expand Down

0 comments on commit 702b082

Please sign in to comment.