mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 22:01:48 +01:00
Merge pull request #10484 from kkmuffme/literal-string-equality-removes-type-incorrectly-and-union-equality-incorrect-type
fix literal int/string comparisons only using one literal
This commit is contained in:
commit
f7fe4cf026
@ -542,9 +542,9 @@ final class AssertionFinder
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// both side of the Identical can be asserted to the intersection of both
|
// 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 = [];
|
$if_types = [];
|
||||||
|
|
||||||
$var_name_left = ExpressionIdentifier::getExtendedVarId(
|
$var_name_left = ExpressionIdentifier::getExtendedVarId(
|
||||||
@ -555,8 +555,13 @@ final class AssertionFinder
|
|||||||
|
|
||||||
$var_assertion_different = $var_type->getId() !== $intersection_type->getId();
|
$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 ($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(
|
$var_name_right = ExpressionIdentifier::getExtendedVarId(
|
||||||
@ -568,7 +573,7 @@ final class AssertionFinder
|
|||||||
$other_assertion_different = $other_type->getId() !== $intersection_type->getId();
|
$other_assertion_different = $other_type->getId() !== $intersection_type->getId();
|
||||||
|
|
||||||
if ($var_name_right && $other_assertion_different) {
|
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] : [];
|
return $if_types ? [$if_types] : [];
|
||||||
|
@ -712,7 +712,9 @@ abstract class Type
|
|||||||
public static function intersectUnionTypes(
|
public static function intersectUnionTypes(
|
||||||
?Union $type_1,
|
?Union $type_1,
|
||||||
?Union $type_2,
|
?Union $type_2,
|
||||||
Codebase $codebase
|
Codebase $codebase,
|
||||||
|
bool $allow_interface_equality = false,
|
||||||
|
bool $allow_float_int_equality = true
|
||||||
): ?Union {
|
): ?Union {
|
||||||
if ($type_2 === null && $type_1 === null) {
|
if ($type_2 === null && $type_1 === null) {
|
||||||
throw new UnexpectedValueException('At least one type must be provided to combine');
|
throw new UnexpectedValueException('At least one type must be provided to combine');
|
||||||
@ -766,6 +768,8 @@ abstract class Type
|
|||||||
$type_2_atomic,
|
$type_2_atomic,
|
||||||
$codebase,
|
$codebase,
|
||||||
$intersection_performed,
|
$intersection_performed,
|
||||||
|
$allow_interface_equality,
|
||||||
|
$allow_float_int_equality,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (null !== $intersection_atomic) {
|
if (null !== $intersection_atomic) {
|
||||||
@ -838,7 +842,9 @@ abstract class Type
|
|||||||
Atomic $type_1_atomic,
|
Atomic $type_1_atomic,
|
||||||
Atomic $type_2_atomic,
|
Atomic $type_2_atomic,
|
||||||
Codebase $codebase,
|
Codebase $codebase,
|
||||||
bool &$intersection_performed
|
bool &$intersection_performed,
|
||||||
|
bool $allow_interface_equality = false,
|
||||||
|
bool $allow_float_int_equality = true
|
||||||
): ?Atomic {
|
): ?Atomic {
|
||||||
$intersection_atomic = null;
|
$intersection_atomic = null;
|
||||||
$wider_type = null;
|
$wider_type = null;
|
||||||
@ -884,6 +890,8 @@ abstract class Type
|
|||||||
$codebase,
|
$codebase,
|
||||||
$type_2_atomic,
|
$type_2_atomic,
|
||||||
$type_1_atomic,
|
$type_1_atomic,
|
||||||
|
$allow_interface_equality,
|
||||||
|
$allow_float_int_equality,
|
||||||
)) {
|
)) {
|
||||||
$intersection_atomic = $type_2_atomic;
|
$intersection_atomic = $type_2_atomic;
|
||||||
$wider_type = $type_1_atomic;
|
$wider_type = $type_1_atomic;
|
||||||
@ -892,6 +900,8 @@ abstract class Type
|
|||||||
$codebase,
|
$codebase,
|
||||||
$type_1_atomic,
|
$type_1_atomic,
|
||||||
$type_2_atomic,
|
$type_2_atomic,
|
||||||
|
$allow_interface_equality,
|
||||||
|
$allow_float_int_equality,
|
||||||
)) {
|
)) {
|
||||||
$intersection_atomic = $type_1_atomic;
|
$intersection_atomic = $type_1_atomic;
|
||||||
$wider_type = $type_2_atomic;
|
$wider_type = $type_2_atomic;
|
||||||
|
@ -580,6 +580,45 @@ class ConditionalTest extends TestCase
|
|||||||
}
|
}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'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' => [
|
'reconcileNullableStringWithWeakEquality' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
function foo(?string $s) : void {
|
function foo(?string $s) : void {
|
||||||
|
@ -272,17 +272,6 @@ class ValueTest extends TestCase
|
|||||||
if ($s === "a") {}
|
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' => [
|
'negativeInts' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
class C {
|
class C {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user