From 2d9133b35a404a017b4b5d4052a3904dad528d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sun, 12 Jun 2022 00:32:36 +0200 Subject: [PATCH] bugfix: overriding types based on assertions have to pass more checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- .../Statements/Expression/CallAnalyzer.php | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index c5c922e10..1111dab5b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -763,7 +763,9 @@ class CallAnalyzer $codebase ); - if ($union->isSingle() || $union->allLiterals()) { + $arg_var_type = $context->vars_in_scope[$assertion_var_id]; + + if (self::isNewTypeNarrowingDownOldType($arg_var_type, $union)) { foreach ($union->getAtomicTypes() as $atomic_type) { if ($assertion_type instanceof TTemplateParam && $assertion_type->as->getId() === $atomic_type->getId() @@ -1117,4 +1119,24 @@ class CallAnalyzer } } } + + /** + * This method should detect if the new type narrows down the old type. + */ + private static function isNewTypeNarrowingDownOldType(Union $old_type, Union $new_type): bool + { + if ($new_type->isSingle()) { + return true; + } + + if ($old_type->hasMixed() && !$new_type->hasMixed()) { + return true; + } + + if ($old_type->isSingleAndMaybeNullable() && !$new_type->isNullable()) { + return true; + } + + return false; + } }