mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix combination of templated types
This commit is contained in:
parent
8ee10ef78c
commit
61d450a267
@ -174,7 +174,6 @@ class SimpleNameResolver extends NodeVisitorAbstract
|
||||
* @template T of Node|null
|
||||
* @param T $node
|
||||
* @return ($node is NullableType ? NullableType : ($node is Name ? Name : T))
|
||||
* @psalm-suppress LessSpecificReturnType
|
||||
*/
|
||||
private function resolveType(?Node $node): ?Node
|
||||
{
|
||||
|
@ -783,6 +783,27 @@ class TypeCombiner
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($type instanceof TTemplateParam) {
|
||||
if (isset($combination->value_types[$type_key])) {
|
||||
/** @var TTemplateParam */
|
||||
$existing_template_type = $combination->value_types[$type_key];
|
||||
|
||||
if (!$existing_template_type->as->equals($type->as)) {
|
||||
$existing_template_type->as = Type::combineUnionTypes(
|
||||
clone $type->as,
|
||||
$existing_template_type->as,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$combination->value_types[$type_key] = $type;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($type instanceof TNamedObject) {
|
||||
if ($combination->named_object_types === null) {
|
||||
return null;
|
||||
|
@ -3637,12 +3637,32 @@ class ClassTemplateTest extends TestCase
|
||||
public function __construct(
|
||||
private object $t
|
||||
) {}
|
||||
|
||||
|
||||
public function foo(): void {
|
||||
if ($this->t instanceof One || $this->t instanceof Two) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final class One {}
|
||||
final class Two {}
|
||||
final class Three {}',
|
||||
],
|
||||
'refineTemplateTypeOfUnionMoreComplex' => [
|
||||
'code' => '<?php
|
||||
/** @psalm-template T as One|Two|Three */
|
||||
class A {
|
||||
/** @param T $t */
|
||||
public function __construct(
|
||||
private object $t
|
||||
) {}
|
||||
|
||||
public function foo(): void {
|
||||
if ($this->t instanceof One && rand(0, 1)) {}
|
||||
|
||||
if ($this->t instanceof Two) {}
|
||||
}
|
||||
}
|
||||
|
||||
final class One {}
|
||||
final class Two {}
|
||||
final class Three {}',
|
||||
@ -4422,10 +4442,33 @@ class ClassTemplateTest extends TestCase
|
||||
|
||||
/** @var Container<A> $container */
|
||||
$container = new Container();
|
||||
$container->set(new B());
|
||||
',
|
||||
$container->set(new B());',
|
||||
'error_message' => 'InvalidArgument',
|
||||
],
|
||||
'refineTemplateTypeOfUnionAccurately' => [
|
||||
'code' => '<?php
|
||||
/** @psalm-template T as One|Two|Three */
|
||||
class A {
|
||||
/** @param T $t */
|
||||
public function __construct(
|
||||
private object $t
|
||||
) {}
|
||||
|
||||
/** @return int */
|
||||
public function foo() {
|
||||
if ($this->t instanceof One || $this->t instanceof Two) {
|
||||
return $this->t;
|
||||
}
|
||||
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
|
||||
final class One {}
|
||||
final class Two {}
|
||||
final class Three {}',
|
||||
'error_message' => 'InvalidReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:40 - The inferred type \'T:A as One|Two\' ',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user