Skip to content

Commit

Permalink
Merge pull request #10484 from kkmuffme/literal-string-equality-remov…
Browse files Browse the repository at this point in the history
…es-type-incorrectly-and-union-equality-incorrect-type

fix literal int/string comparisons only using one literal
  • Loading branch information
orklah committed Dec 13, 2023
2 parents 955e7fe + cceb1fb commit f7fe4cf
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,9 @@ private static function scrapeEqualityAssertions(
);
} else {
// both side of the Identical can be asserted to the intersection of both
$intersection_type = Type::intersectUnionTypes($var_type, $other_type, $codebase);
$intersection_type = Type::intersectUnionTypes($var_type, $other_type, $codebase, false, false);

if ($intersection_type !== null && $intersection_type->isSingle()) {
if ($intersection_type !== null) {
$if_types = [];

$var_name_left = ExpressionIdentifier::getExtendedVarId(
Expand All @@ -555,8 +555,13 @@ private static function scrapeEqualityAssertions(

$var_assertion_different = $var_type->getId() !== $intersection_type->getId();

$all_assertions = [];
foreach ($intersection_type->getAtomicTypes() as $atomic_type) {
$all_assertions[] = new IsIdentical($atomic_type);
}

if ($var_name_left && $var_assertion_different) {
$if_types[$var_name_left] = [[new IsIdentical($intersection_type->getSingleAtomic())]];
$if_types[$var_name_left] = [$all_assertions];
}

$var_name_right = ExpressionIdentifier::getExtendedVarId(
Expand All @@ -568,7 +573,7 @@ private static function scrapeEqualityAssertions(
$other_assertion_different = $other_type->getId() !== $intersection_type->getId();

if ($var_name_right && $other_assertion_different) {
$if_types[$var_name_right] = [[new IsIdentical($intersection_type->getSingleAtomic())]];
$if_types[$var_name_right] = [$all_assertions];
}

return $if_types ? [$if_types] : [];
Expand Down
14 changes: 12 additions & 2 deletions src/Psalm/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,9 @@ public static function combineUnionTypes(
public static function intersectUnionTypes(
?Union $type_1,
?Union $type_2,
Codebase $codebase
Codebase $codebase,
bool $allow_interface_equality = false,
bool $allow_float_int_equality = true
): ?Union {
if ($type_2 === null && $type_1 === null) {
throw new UnexpectedValueException('At least one type must be provided to combine');
Expand Down Expand Up @@ -766,6 +768,8 @@ public static function intersectUnionTypes(
$type_2_atomic,
$codebase,
$intersection_performed,
$allow_interface_equality,
$allow_float_int_equality,
);

if (null !== $intersection_atomic) {
Expand Down Expand Up @@ -838,7 +842,9 @@ private static function intersectAtomicTypes(
Atomic $type_1_atomic,
Atomic $type_2_atomic,
Codebase $codebase,
bool &$intersection_performed
bool &$intersection_performed,
bool $allow_interface_equality = false,
bool $allow_float_int_equality = true
): ?Atomic {
$intersection_atomic = null;
$wider_type = null;
Expand Down Expand Up @@ -884,6 +890,8 @@ private static function intersectAtomicTypes(
$codebase,
$type_2_atomic,
$type_1_atomic,
$allow_interface_equality,
$allow_float_int_equality,
)) {
$intersection_atomic = $type_2_atomic;
$wider_type = $type_1_atomic;
Expand All @@ -892,6 +900,8 @@ private static function intersectAtomicTypes(
$codebase,
$type_1_atomic,
$type_2_atomic,
$allow_interface_equality,
$allow_float_int_equality,
)) {
$intersection_atomic = $type_1_atomic;
$wider_type = $type_2_atomic;
Expand Down
39 changes: 39 additions & 0 deletions tests/TypeReconciliation/ConditionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,45 @@ function foo($a, string $b) : void {
}
}',
],
'reconcileMultipleLiteralStrings' => [
'code' => '<?php
/**
* @param string $param
* @param "a"|"b"|"c" $param2
* @return void
*/
function foo($param, $param2) {
if ( $param === $param2 ) {
if ($param === "a") {
echo "x";
}
if ($param === "b") {
echo "y";
}
if ($param === "c") {
echo "z";
}
}
}',
],
'reconcileMultipleUnionIntersection' => [
'code' => '<?php
/**
* @param int|string $param
* @param float|string $param2
* @return void
*/
function foo($param, $param2) {
if ($param === $param2) {
takesString($param);
takesString($param2);
}
}
function takesString(string $arg): void {}',
],
'reconcileNullableStringWithWeakEquality' => [
'code' => '<?php
function foo(?string $s) : void {
Expand Down
11 changes: 0 additions & 11 deletions tests/TypeReconciliation/ValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,17 +272,6 @@ function foo($f) : void {
if ($s === "a") {}
}',
],
'moreValueReconciliation' => [
'code' => '<?php
$a = rand(0, 1) ? "a" : "b";
$b = rand(0, 1) ? "a" : "b";
$s = rand(0, 1) ? $a : $b;
if (rand(0, 1)) $s = "c";
if ($s === $a) {
} elseif ($s === $b) {}',
],
'negativeInts' => [
'code' => '<?php
class C {
Expand Down

0 comments on commit f7fe4cf

Please sign in to comment.