mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 13:51:54 +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 {
|
||||
// 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(
|
||||
@ -555,8 +555,13 @@ final class AssertionFinder
|
||||
|
||||
$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(
|
||||
@ -568,7 +573,7 @@ final class AssertionFinder
|
||||
$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] : [];
|
||||
|
@ -712,7 +712,9 @@ abstract class Type
|
||||
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');
|
||||
@ -766,6 +768,8 @@ abstract class Type
|
||||
$type_2_atomic,
|
||||
$codebase,
|
||||
$intersection_performed,
|
||||
$allow_interface_equality,
|
||||
$allow_float_int_equality,
|
||||
);
|
||||
|
||||
if (null !== $intersection_atomic) {
|
||||
@ -838,7 +842,9 @@ abstract class Type
|
||||
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;
|
||||
@ -884,6 +890,8 @@ abstract class Type
|
||||
$codebase,
|
||||
$type_2_atomic,
|
||||
$type_1_atomic,
|
||||
$allow_interface_equality,
|
||||
$allow_float_int_equality,
|
||||
)) {
|
||||
$intersection_atomic = $type_2_atomic;
|
||||
$wider_type = $type_1_atomic;
|
||||
@ -892,6 +900,8 @@ abstract class Type
|
||||
$codebase,
|
||||
$type_1_atomic,
|
||||
$type_2_atomic,
|
||||
$allow_interface_equality,
|
||||
$allow_float_int_equality,
|
||||
)) {
|
||||
$intersection_atomic = $type_1_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' => [
|
||||
'code' => '<?php
|
||||
function foo(?string $s) : void {
|
||||
|
@ -272,17 +272,6 @@ class ValueTest extends TestCase
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user