From 5b7d1906408c40f6c0292ea1072f5874a4300454 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Tue, 17 Apr 2018 15:39:09 -0400 Subject: [PATCH] Emit RedundantCondition when asserting two variables can never be equal --- .../Checker/Statements/Block/TryChecker.php | 6 +- .../Statements/Expression/AssertionFinder.php | 64 +++++++++++++++++++ tests/TypeAlgebraTest.php | 7 ++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/Psalm/Checker/Statements/Block/TryChecker.php b/src/Psalm/Checker/Statements/Block/TryChecker.php index f4f422a61..43700347a 100644 --- a/src/Psalm/Checker/Statements/Block/TryChecker.php +++ b/src/Psalm/Checker/Statements/Block/TryChecker.php @@ -275,9 +275,9 @@ class TryChecker if ($catch_actions[$i] !== [ScopeChecker::ACTION_END]) { foreach ($catch_context->vars_in_scope as $var_id => $type) { - if ($catch->var !== $var_id && - $context->hasVariable($var_id) && - $context->vars_in_scope[$var_id]->getId() !== $type->getId() + if ((!is_string($catch->var->name) || ('$' . $catch->var->name) !== $var_id) + && $context->hasVariable($var_id) + && $context->vars_in_scope[$var_id]->getId() !== $type->getId() ) { $context->vars_in_scope[$var_id] = Type::combineUnionTypes( $context->vars_in_scope[$var_id], diff --git a/src/Psalm/Checker/Statements/Expression/AssertionFinder.php b/src/Psalm/Checker/Statements/Expression/AssertionFinder.php index ca39966f2..63f086ffc 100644 --- a/src/Psalm/Checker/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Checker/Statements/Expression/AssertionFinder.php @@ -7,6 +7,7 @@ use Psalm\Checker\Statements\ExpressionChecker; use Psalm\Checker\TypeChecker; use Psalm\CodeLocation; use Psalm\FileSource; +use Psalm\Issue\RedundantCondition; use Psalm\Issue\TypeDoesNotContainNull; use Psalm\Issue\TypeDoesNotContainType; use Psalm\Issue\UnevaluatedCode; @@ -442,6 +443,7 @@ class AssertionFinder $true_position = self::hasTrueVariable($conditional); $gettype_position = self::hasGetTypeCheck($conditional); $getclass_position = self::hasGetClassCheck($conditional); + $typed_value_position = self::hasTypedValueComparison($conditional); if ($null_position !== null) { if ($null_position === self::ASSIGNMENT_TO_RIGHT) { @@ -621,6 +623,68 @@ class AssertionFinder return $if_types; } + if ($typed_value_position) { + if ($typed_value_position === self::ASSIGNMENT_TO_RIGHT) { + /** @var PhpParser\Node\Expr $conditional->right */ + $var_name = ExpressionChecker::getArrayVarId( + $conditional->left, + $this_class_name, + $source + ); + + $other_type = isset($conditional->left->inferredType) ? $conditional->left->inferredType : null; + $var_type = isset($conditional->right->inferredType) ? $conditional->right->inferredType : null; + } elseif ($typed_value_position === self::ASSIGNMENT_TO_LEFT) { + /** @var PhpParser\Node\Expr $conditional->left */ + $var_name = ExpressionChecker::getArrayVarId( + $conditional->right, + $this_class_name, + $source + ); + + $var_type = isset($conditional->left->inferredType) ? $conditional->left->inferredType : null; + $other_type = isset($conditional->right->inferredType) ? $conditional->right->inferredType : null; + } else { + throw new \UnexpectedValueException('$typed_value_position value'); + } + + if ($var_type) { + if ($var_name) { + $if_types[$var_name] = '!^' . $var_type; + } + + if ($other_type + && $conditional instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical + && $source instanceof StatementsSource + && $project_checker + ) { + if (!TypeChecker::isContainedBy( + $project_checker->codebase, + $var_type, + $other_type, + true + ) && !TypeChecker::isContainedBy( + $project_checker->codebase, + $other_type, + $var_type, + true + )) { + if (IssueBuffer::accepts( + new RedundantCondition( + $var_type . ' can never contain ' . $other_type, + new CodeLocation($source, $conditional) + ), + $source->getSuppressedIssues() + )) { + // fall through + } + } + } + } + + return $if_types; + } + return []; } diff --git a/tests/TypeAlgebraTest.php b/tests/TypeAlgebraTest.php index a0995ba19..3d3732970 100644 --- a/tests/TypeAlgebraTest.php +++ b/tests/TypeAlgebraTest.php @@ -764,6 +764,13 @@ class TypeAlgebraTest extends TestCase }', 'error_message' => 'ParadoxicalCondition', ], + 'typeDoesntEqualType' => [ + ' 'RedundantCondition', + ], ]; } }