1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Type negation in generic context (#5879)

* Type negation in generic context

* Fix cs
This commit is contained in:
Andrey Klimenko 2021-06-03 08:06:25 +03:00 committed by GitHub
parent 1a2e761918
commit e5e397a6c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View File

@ -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)

View File

@ -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;

View File

@ -2589,6 +2589,43 @@ class ConditionalTest extends \Psalm\Tests\TestCase
'$c' => 'list<float|int>',
],
],
'negateTypeInGenericContext' => [
'<?php
/**
* @template T
*/
final class Valid {}
final class Invalid {}
/**
* @template T
*
* @param Valid<T>|Invalid $val
* @psalm-assert-if-true Valid<T> $val
*/
function isValid($val): bool
{
return $val instanceof Valid;
}
/**
* @template T
* @param Valid<T>|Invalid $val
*/
function genericContext($val): void
{
$takesValid =
/** @param Valid<T> $_valid */
function ($_valid): void {};
$takesInvalid =
/** @param Invalid $_invalid */
function ($_invalid): void {};
isValid($val) ? $takesValid($val) : $takesInvalid($val);
}'
],
];
}