1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Fix #3082 - merge intersection types when replacing template types

This commit is contained in:
Brown 2020-04-06 10:19:30 -04:00
parent 6ac6c54a34
commit 387bc02e71
3 changed files with 45 additions and 1 deletions

View File

@ -754,6 +754,12 @@ class AssertionReconciler extends \Psalm\Type\Reconciler
$existing_var_type_part->addIntersectionType($new_type_part);
$acceptable_atomic_types[] = $existing_var_type_part;
}
if ($existing_var_type_part instanceof TTemplateParam) {
$existing_var_type_part = clone $existing_var_type_part;
$existing_var_type_part->addIntersectionType($new_type_part);
$acceptable_atomic_types[] = $existing_var_type_part;
}
}
if ($acceptable_atomic_types) {

View File

@ -1166,7 +1166,10 @@ class Union implements TypeNode
|| $atomic_template_type instanceof TIterable
|| $atomic_template_type instanceof Type\Atomic\TObjectWithProperties
) {
$atomic_template_type->extra_types = $atomic_type->extra_types;
$atomic_template_type->extra_types = array_merge(
$atomic_type->extra_types,
$atomic_template_type->extra_types ?: []
);
} elseif ($atomic_template_type instanceof Type\Atomic\TObject) {
$first_atomic_type = array_shift($atomic_type->extra_types);

View File

@ -1152,6 +1152,41 @@ class FunctionTemplateTest extends TestCase
createProxy(Foo::class, function (?Foo $f) : void {});'
],
'assertIntersectionsOnTemplatedTypes' => [
'<?php
interface Input {}
interface HasFoo {}
interface HasBar {}
/**
* @psalm-template InputType of Input
* @psalm-param InputType $input
* @psalm-return InputType&HasFoo
*/
function decorateWithFoo(Input $input): Input
{
assert($input instanceof HasFoo);
return $input;
}
/**
* @psalm-template InputType of Input
* @psalm-param InputType $input
* @psalm-return InputType&HasBar
*/
function decorateWithBar(Input $input): Input
{
assert($input instanceof HasBar);
return $input;
}
/** @param HasFoo&HasBar $input */
function useFooAndBar(object $input): void {}
function consume(Input $input): void {
useFooAndBar(decorateWithFoo(decorateWithBar($input)));
}'
],
];
}