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

Fix #2756 - narrow assertion templated type

This commit is contained in:
Brown 2020-02-06 11:49:15 -05:00
parent ffd04132ce
commit a16e03d992
2 changed files with 70 additions and 0 deletions

View File

@ -684,6 +684,30 @@ class AssertionReconciler extends \Psalm\Type\Reconciler
}
}
if ($new_type_part instanceof Type\Atomic\TTemplateParam
&& $new_type_part->as->isSingle()
) {
$new_as_atomic = array_values($new_type_part->as->getAtomicTypes())[0];
$acceptable_atomic_types = [];
foreach ($existing_var_type->getAtomicTypes() as $existing_var_type_part) {
if (TypeAnalyzer::isAtomicContainedBy(
$codebase,
$existing_var_type_part,
$new_as_atomic
)) {
$acceptable_atomic_types[] = clone $existing_var_type_part;
continue;
}
}
if ($acceptable_atomic_types) {
$new_type_part->as = new Type\Union($acceptable_atomic_types);
return new Type\Union([$new_type_part]);
}
}
if ($new_type_part instanceof TNamedObject
&& ((
$new_type_has_interface

View File

@ -631,6 +631,52 @@ class FunctionTemplateAssertTest extends TestCase
return $anyString;
}'
],
'classTemplateAssert' => [
'<?php
/**
* @template ActualFieldType
*/
final class FieldValue
{
/** @var ActualFieldType */
public $value;
/** @param ActualFieldType $value */
public function __construct($value) {
$this->value = $value;
}
}
/**
* @template FieldDefinitionType
*
* @param string|bool|int|null $value
* @param FieldDefinition<FieldDefinitionType> $definition
*
* @return FieldValue<FieldDefinitionType>
*/
function fromScalarAndDefinition($value, FieldDefinition $definition) : FieldValue
{
$definition->assertAppliesToValue($value);
return new FieldValue($value);
}
/**
* @template ExpectedFieldType
*/
final class FieldDefinition
{
/**
* @param mixed $value
* @psalm-assert ExpectedFieldType $value
*/
public function assertAppliesToValue($value): void
{
throw new \Exception("bad");
}
}'
],
];
}