From 586c70c8d39a2ebad3b1b17c4b050dc4e5e6f05f Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 13 Feb 2022 17:43:40 +0100 Subject: [PATCH 1/4] Reconcile IsNotType between EnumCase and NamedObject --- .../Internal/Type/NegatedAssertionReconciler.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index e710a8c3c7d..74f4d1cf782 100644 --- a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -16,7 +16,6 @@ use Psalm\Type\Atomic; use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TClassString; -use Psalm\Type\Atomic\TEmptyMixed; use Psalm\Type\Atomic\TEnumCase; use Psalm\Type\Atomic\TFalse; use Psalm\Type\Atomic\TFloat; @@ -162,6 +161,14 @@ public static function reconcile( return $existing_var_type; } + if (!$is_equality && $assertion_type instanceof TNamedObject) { + foreach ($existing_var_type->getAtomicTypes() as $key => $type) { + if ($type instanceof TEnumCase && $type->value === $assertion_type->value) { + $existing_var_type->removeType($key); + } + } + } + $codebase = $statements_analyzer->getCodebase(); if ($assertion_type instanceof TNamedObject @@ -291,7 +298,7 @@ public static function reconcile( $failed_reconciliation = Reconciler::RECONCILIATION_EMPTY; - return new Union([new TEmptyMixed]); + return Type::getNever(); } return $existing_var_type; From 5f1b796af999d9eac549e0d0bac426605ff1580e Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 13 Feb 2022 17:50:43 +0100 Subject: [PATCH 2/4] redundant condition --- src/Psalm/Internal/Provider/StatementsProvider.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Psalm/Internal/Provider/StatementsProvider.php b/src/Psalm/Internal/Provider/StatementsProvider.php index f78bd3e83b9..d6d5d4abccc 100644 --- a/src/Psalm/Internal/Provider/StatementsProvider.php +++ b/src/Psalm/Internal/Provider/StatementsProvider.php @@ -155,10 +155,6 @@ public function getStatementsForFile( $existing_statements = $this->parser_cache_provider->loadExistingStatementsFromCache($file_path); - if ($existing_statements && !$existing_statements[0] instanceof PhpParser\Node\Stmt) { - $existing_statements = null; - } - $existing_file_contents = $this->parser_cache_provider->loadExistingFileContentsFromCache($file_path); // this happens after editing temporary file From aaf34d75734d4a238a00eab92f5f7c53aadad781 Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 13 Feb 2022 19:05:51 +0100 Subject: [PATCH 3/4] add test --- tests/EnumTest.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 3297151ee2d..963614bd198 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -405,6 +405,35 @@ function foo(): int|Code|null 'ignored_issues' => [], 'php_version' => '8.1', ], + 'EnumCaseReconciliation' => [ + 'code' => ' [ + '$code1' => 'Code|null', + '$code2' => 'null', + ], + 'ignored_issues' => [], + 'php_version' => '8.1', + ], ]; } From 093d9b28212d949e570a73cafbc96b93b4f7f1d8 Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 13 Feb 2022 19:44:12 +0100 Subject: [PATCH 4/4] allow use of an empty reconciliation if the type is from docblock --- src/Psalm/Internal/Type/NegatedAssertionReconciler.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index 74f4d1cf782..efdf02d80c6 100644 --- a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -298,7 +298,9 @@ public static function reconcile( $failed_reconciliation = Reconciler::RECONCILIATION_EMPTY; - return Type::getNever(); + return $existing_var_type->from_docblock + ? Type::getMixed() + : Type::getNever(); } return $existing_var_type;