mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Assert intersection type when two variables are compared (#5774)
This commit is contained in:
parent
3c43bc1522
commit
f62b83a190
@ -596,10 +596,6 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer
|
|||||||
return $emit_issues ? null : true;
|
return $emit_issues ? null : true;
|
||||||
|
|
||||||
case self::VISIBILITY_PROTECTED:
|
case self::VISIBILITY_PROTECTED:
|
||||||
if ($appearing_property_class === $context->self) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$context->self) {
|
if (!$context->self) {
|
||||||
if ($emit_issues && IssueBuffer::accepts(
|
if ($emit_issues && IssueBuffer::accepts(
|
||||||
new InaccessibleProperty(
|
new InaccessibleProperty(
|
||||||
|
@ -437,6 +437,40 @@ class AssertionFinder
|
|||||||
)) {
|
)) {
|
||||||
// fall through
|
// fall through
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// both side of the Identical can be asserted to the intersection of both
|
||||||
|
$intersection_type = Type::intersectUnionTypes($var_type, $other_type, $codebase);
|
||||||
|
|
||||||
|
if ($intersection_type !== null && $intersection_type->isSingle()) {
|
||||||
|
$assertion = $intersection_type->getAssertionString();
|
||||||
|
|
||||||
|
$if_types = [];
|
||||||
|
|
||||||
|
$var_name_left = ExpressionIdentifier::getArrayVarId(
|
||||||
|
$conditional->left,
|
||||||
|
$this_class_name,
|
||||||
|
$source
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($var_name_left &&
|
||||||
|
(!$var_type->isSingle() || $var_type->getAssertionString() !== $assertion)) {
|
||||||
|
$if_types[$var_name_left] = [['~'.$assertion]];
|
||||||
|
}
|
||||||
|
|
||||||
|
$var_name_right = ExpressionIdentifier::getArrayVarId(
|
||||||
|
$conditional->right,
|
||||||
|
$this_class_name,
|
||||||
|
$source
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($var_name_right &&
|
||||||
|
(!$other_type->isSingle() || $other_type->getAssertionString() !== $assertion)) {
|
||||||
|
$if_types[$var_name_right] = [['~'.$assertion]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $if_types ? [$if_types] : [];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Psalm;
|
namespace Psalm;
|
||||||
|
|
||||||
|
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||||
use Psalm\Plugin\EventHandler\Event\StringInterpreterEvent;
|
use Psalm\Plugin\EventHandler\Event\StringInterpreterEvent;
|
||||||
use Psalm\Type\Atomic\TNever;
|
use Psalm\Type\Atomic\TNever;
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
@ -649,6 +650,19 @@ abstract class Type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if a type is contained by the other, the intersection is the narrowest type
|
||||||
|
if (!$intersection_performed) {
|
||||||
|
$type_1_in_2 = UnionTypeComparator::isContainedBy($codebase, $type_1, $type_2);
|
||||||
|
$type_2_in_1 = UnionTypeComparator::isContainedBy($codebase, $type_2, $type_1);
|
||||||
|
if ($type_1_in_2) {
|
||||||
|
$intersection_performed = true;
|
||||||
|
$combined_type = $type_1;
|
||||||
|
} elseif ($type_2_in_1) {
|
||||||
|
$intersection_performed = true;
|
||||||
|
$combined_type = $type_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!$type_1->initialized && !$type_2->initialized) {
|
if (!$type_1->initialized && !$type_2->initialized) {
|
||||||
$combined_type->initialized = false;
|
$combined_type->initialized = false;
|
||||||
}
|
}
|
||||||
|
@ -1093,6 +1093,15 @@ class TypeAlgebraTest extends \Psalm\Tests\TestCase
|
|||||||
[],
|
[],
|
||||||
'8.1',
|
'8.1',
|
||||||
],
|
],
|
||||||
|
'narrowedTypeAfterIdenticalCheckWithOtherType' => [
|
||||||
|
'<?php
|
||||||
|
function a(int $a, ?int $b = null): void
|
||||||
|
{
|
||||||
|
if ($a === $b) {
|
||||||
|
throw new InvalidArgumentException(sprintf("a can not be the same as b (b: %s).", $b));
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user