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

Merge pull request #9679 from robchett/mixedAssignment_from_template_var

Don't throw UnnecesseryVarAnnotation when hinting a mixed template var
This commit is contained in:
orklah 2023-04-20 23:52:52 +02:00 committed by GitHub
commit b781bd922e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 4 deletions

View File

@ -191,7 +191,7 @@ class ForeachAnalyzer
&& $type_location
&& isset($context->vars_in_scope[$var_comment->var_id])
&& $context->vars_in_scope[$var_comment->var_id]->getId() === $comment_type->getId()
&& !$comment_type->isMixed()
&& !$comment_type->isMixed(true)
) {
$project_analyzer = $statements_analyzer->getProjectAnalyzer();

View File

@ -270,7 +270,7 @@ class AssignmentAnalyzer
&& $extended_var_id
&& (!$not_ignored_docblock_var_ids || isset($not_ignored_docblock_var_ids[$extended_var_id]))
&& $temp_assign_value_type->getId() === $comment_type->getId()
&& !$comment_type->isMixed()
&& !$comment_type->isMixed(true)
) {
if ($codebase->alter_code
&& isset($statements_analyzer->getProjectAnalyzer()->getIssuesToFix()['UnnecessaryVarAnnotation'])

View File

@ -53,6 +53,8 @@ use function reset;
use function sort;
use function strpos;
use const ARRAY_FILTER_USE_BOTH;
/**
* @psalm-immutable
* @psalm-import-type TProperties from Union
@ -796,9 +798,20 @@ trait UnionTrait
/**
* @psalm-mutation-free
*/
public function isMixed(): bool
public function isMixed(bool $check_templates = false): bool
{
return isset($this->types['mixed']) && count($this->types) === 1;
return count(
array_filter(
$this->types,
static fn($type, $key): bool => $key === 'mixed'
|| $type instanceof TMixed
|| ($check_templates
&& $type instanceof TTemplateParam
&& $type->as->isMixed()
),
ARRAY_FILTER_USE_BOTH,
),
) === count($this->types);
}
/**

View File

@ -4112,6 +4112,32 @@ class ClassTemplateTest extends TestCase
'$t===' => '\'\'',
],
],
'mixedAssignment' => [
'code' => '<?php
/** @template T */
abstract class Foo {
/** @psalm-var T */
protected $value;
/** @psalm-param T $value */
public function __construct($value)
{
/** @var T */
$value = $this->normalize($value);
$this->value = $value;
}
/**
* @psalm-param T $value
* @psalm-return T
*/
protected function normalize($value)
{
return $value;
}
}
',
],
];
}