diff --git a/docs/running_psalm/issues/ParadoxicalCondition.md b/docs/running_psalm/issues/ParadoxicalCondition.md index 4d355f6cd..334b1b351 100644 --- a/docs/running_psalm/issues/ParadoxicalCondition.md +++ b/docs/running_psalm/issues/ParadoxicalCondition.md @@ -5,11 +5,7 @@ Emitted when a paradox is encountered in your programs logic that could not be c ```php isNegation()) { - $things_that_can_be_said[(string)$assertion] = $assertion; - } + $things_that_can_be_said[(string)$assertion] = $assertion; } - if ($things_that_can_be_said && count($things_that_can_be_said) === count($possible_types)) { - if ($clause->generated && count($possible_types) > 1) { - unset($cond_referenced_var_ids[$var]); - } + if ($clause->generated && count($possible_types) > 1) { + unset($cond_referenced_var_ids[$var]); + } - $truths[$var] = [array_values($things_that_can_be_said)]; + $truths[$var] = [array_values($things_that_can_be_said)]; - if ($creating_conditional_id && $creating_conditional_id === $clause->creating_conditional_id) { - $active_truths[$var] = [array_values($things_that_can_be_said)]; - } + if ($creating_conditional_id && $creating_conditional_id === $clause->creating_conditional_id) { + $active_truths[$var] = [array_values($things_that_can_be_said)]; } } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php index 1abf90ffc..a5a006a0b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php @@ -272,6 +272,9 @@ class IfElseAnalyzer // this has to go on a separate line because the phar compactor messes with precedence $scope_to_clone = $if_scope->post_leaving_if_context ?? $post_if_context; $else_context = clone $scope_to_clone; + $else_context->clauses = Algebra::simplifyCNF( + [...$else_context->clauses, ...$if_scope->negated_clauses], + ); // check the elseifs foreach ($stmt->elseifs as $elseif) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php index 5732707b9..e5cca5b8a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php @@ -151,7 +151,10 @@ class AndAnalyzer $right_context = clone $left_context; } - $partitioned_clauses = Context::removeReconciledClauses($left_clauses, $changed_var_ids); + $partitioned_clauses = Context::removeReconciledClauses( + [...$left_context->clauses, ...$left_clauses], + $changed_var_ids + ); $right_context->clauses = $partitioned_clauses[0]; diff --git a/tests/AssertAnnotationTest.php b/tests/AssertAnnotationTest.php index 8630d068a..f41c95769 100644 --- a/tests/AssertAnnotationTest.php +++ b/tests/AssertAnnotationTest.php @@ -2110,6 +2110,22 @@ class AssertAnnotationTest extends TestCase consumeAOrB($abc); ', ], + 'assertDocblockTypeContradictionCorrectType' => [ + 'code' => ' [], 'php_version' => '8.0', ], + 'subclassAfterNegation' => [ + 'code' => 's; + } + } + }' + ], + 'subclassAfterElseifNegation' => [ + 'code' => 's; + } + }' + ], ]; } @@ -1347,14 +1381,15 @@ class TypeAlgebraTest extends TestCase ], 'repeatedAndConditional' => [ 'code' => ' 'ParadoxicalCondition', + 'error_message' => 'TypeDoesNotContainType', ], 'andConditionalAfterOrConditional' => [ 'code' => '