1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 12:24:49 +01:00

Fix #5029 - remember staticness of types when combining

This commit is contained in:
Matt Brown 2021-01-16 01:12:18 -05:00 committed by Daniil Gentili
parent b71ff1109a
commit d81d57a30e
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
4 changed files with 65 additions and 10 deletions

View File

@ -24,6 +24,9 @@ class TypeCombination
/** @var array<string, non-empty-list<Union>> */
public $object_type_params = [];
/** @var array<string, bool> */
public $object_static = [];
/** @var array<int, bool>|null */
public $array_counts = [];

View File

@ -243,6 +243,7 @@ class TypeCombiner
$new_types[] = new TIterable($generic_type_params);
} else {
$generic_object = new TGenericObject($generic_type, $generic_type_params);
/** @psalm-suppress PropertyTypeCoercion */
$generic_object->extra_types = $combination->extra_types;
$new_types[] = $generic_object;
@ -257,6 +258,11 @@ class TypeCombiner
$generic_type = substr($generic_type, 0, (int) strpos($generic_type, '<'));
$generic_object = new TGenericObject($generic_type, $generic_type_params);
if ($combination->object_static[$generic_type] ?? false) {
$generic_object->was_static = true;
}
/** @psalm-suppress PropertyTypeCoercion */
$generic_object->extra_types = $combination->extra_types;
$new_types[] = $generic_object;
@ -492,6 +498,16 @@ class TypeCombiner
}
}
if ($type instanceof TNamedObject) {
if (\array_key_exists($type->value, $combination->object_static)) {
if ($combination->object_static[$type->value] && !$type->was_static) {
$combination->object_static[$type->value] = false;
}
} else {
$combination->object_static[$type->value] = $type->was_static;
}
}
if ($type instanceof TArray && $type_key === 'array') {
if ($type instanceof TCallableArray && isset($combination->value_types['callable'])) {
return null;

View File

@ -45,7 +45,8 @@ trait GenericTrait
$extra_types = '';
if ($this instanceof TNamedObject && $this->extra_types) {
if ($this instanceof TNamedObject) {
if ($this->extra_types) {
$extra_types = '&' . implode(
'&',
array_map(
@ -57,6 +58,11 @@ trait GenericTrait
);
}
if ($this->was_static) {
$extra_types .= '&static';
}
}
return $this->value . '<' . substr($s, 0, -2) . '>' . $extra_types;
}

View File

@ -3278,6 +3278,36 @@ class ClassTemplateTest extends TestCase
}
}'
],
'templatedStaticUnion' => [
'<?php
/**
* @template T
*/
abstract class A {
/**
* @var T
*/
private $v;
/**
* @param T $v
*/
final public function __construct($v) {
$this->v = $v;
}
/**
* @return static<T>
*/
public function foo(): A {
if (rand(0, 1)) {
return new static($this->v);
} else {
return new static($this->v);
}
}
}'
],
];
}