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;
|
||||
|
||||
case self::VISIBILITY_PROTECTED:
|
||||
if ($appearing_property_class === $context->self) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$context->self) {
|
||||
if ($emit_issues && IssueBuffer::accepts(
|
||||
new InaccessibleProperty(
|
||||
|
@ -437,6 +437,40 @@ class AssertionFinder
|
||||
)) {
|
||||
// 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
|
||||
namespace Psalm;
|
||||
|
||||
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||
use Psalm\Plugin\EventHandler\Event\StringInterpreterEvent;
|
||||
use Psalm\Type\Atomic\TNever;
|
||||
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) {
|
||||
$combined_type->initialized = false;
|
||||
}
|
||||
|
@ -1093,6 +1093,15 @@ class TypeAlgebraTest extends \Psalm\Tests\TestCase
|
||||
[],
|
||||
'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