From 3a87f18b5a786a27c6e52bcf8df10418d6d7cdbe Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Sat, 1 May 2021 20:00:01 -0400 Subject: [PATCH] Fix #5685 - properly negate complex conditionals --- src/Psalm/Type/Reconciler.php | 21 ++++++++++++++----- .../AssignmentInConditionalTest.php | 7 +++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Psalm/Type/Reconciler.php b/src/Psalm/Type/Reconciler.php index af775b7a3..b0a036b8a 100644 --- a/src/Psalm/Type/Reconciler.php +++ b/src/Psalm/Type/Reconciler.php @@ -160,9 +160,20 @@ class Reconciler $orred_type = null; foreach ($new_type_part_parts as $new_type_part_part) { - if ($new_type_part_part[0] === '>') { - /** @var array>> */ - $data = \json_decode(substr($new_type_part_part, 1), true); + if ($new_type_part_part[0] === '>' + || ($new_type_part_part[0] === '!' + && $new_type_part_part[1] === '>') + ) { + if ($new_type_part_part[0] === '!') { + $nested_negated = !$negated; + + /** @var array>> */ + $data = \json_decode(substr($new_type_part_part, 2), true); + } else { + $nested_negated = $negated; + /** @var array>> */ + $data = \json_decode(substr($new_type_part_part, 1), true); + } $existing_types = self::reconcileKeyedTypes( $data, @@ -174,10 +185,10 @@ class Reconciler $template_type_map, $inside_loop, $code_location, - $negated + $nested_negated ); - $new_type_part_part = '!falsy'; + $new_type_part_part = ($nested_negated ? '' : '!') . 'falsy'; } $result_type_candidate = AssertionReconciler::reconcile( diff --git a/tests/TypeReconciliation/AssignmentInConditionalTest.php b/tests/TypeReconciliation/AssignmentInConditionalTest.php index 146c7be0b..dfe0aecf8 100644 --- a/tests/TypeReconciliation/AssignmentInConditionalTest.php +++ b/tests/TypeReconciliation/AssignmentInConditionalTest.php @@ -449,6 +449,13 @@ class AssignmentInConditionalTest extends \Psalm\Tests\TestCase [], '8.0' ], + 'assignmentForComparison' => [ + ' 1) {} + if ($a) {} + }' + ], ]; }