diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php index df392e18e..524b10f52 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php @@ -73,7 +73,7 @@ class ElseAnalyzer $changed_var_ids, [], $statements_analyzer, - [], + $statements_analyzer->getTemplateTypeMap() ?: [], $else_context->inside_loop, $else ? new CodeLocation($statements_analyzer->getSource(), $else, $outer_context->include_location) diff --git a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index de312eabd..ae4ebeaf7 100644 --- a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -13,7 +13,6 @@ use Psalm\Issue\RedundantPropertyInitializationCheck; use Psalm\Internal\Type\Comparator\UnionTypeComparator; use Psalm\IssueBuffer; use Psalm\Type; -use Psalm\Type\Atomic; use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TFalse; use Psalm\Type\Atomic\TNamedObject; @@ -25,6 +24,7 @@ use function strtolower; use function substr; use function explode; use function get_class; +use function array_values; class NegatedAssertionReconciler extends Reconciler { @@ -238,7 +238,13 @@ class NegatedAssertionReconciler extends Reconciler continue; } - $new_type_part = Atomic::create($assertion, null, $template_type_map); + $assertion_type = Type::parseString($assertion, null, $template_type_map); + + if (!$assertion_type->isSingle()) { + continue; + } + + $new_type_part = array_values($assertion_type->getAtomicTypes())[0]; if (!$new_type_part instanceof TNamedObject) { continue; diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index d89f790fc..5f0ba8bd0 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -2589,6 +2589,43 @@ class ConditionalTest extends \Psalm\Tests\TestCase '$c' => 'list', ], ], + 'negateTypeInGenericContext' => [ + '|Invalid $val + * @psalm-assert-if-true Valid $val + */ + function isValid($val): bool + { + return $val instanceof Valid; + } + + /** + * @template T + * @param Valid|Invalid $val + */ + function genericContext($val): void + { + $takesValid = + /** @param Valid $_valid */ + function ($_valid): void {}; + + $takesInvalid = + /** @param Invalid $_invalid */ + function ($_invalid): void {}; + + isValid($val) ? $takesValid($val) : $takesInvalid($val); + }' + ], ]; }