mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Fix #3535 - match template param class constants properly
This commit is contained in:
parent
74a34f066c
commit
ce445636e7
@ -412,7 +412,7 @@ class ReturnAnalyzer
|
||||
} else {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidReturnStatement(
|
||||
'The inferred type \'' . $stmt_type->getId()
|
||||
'The inferred type \'' . $inferred_type->getId()
|
||||
. '\' does not match the declared return '
|
||||
. 'type \'' . $local_return_type->getId() . '\' for ' . $cased_method_id,
|
||||
new CodeLocation($source, $stmt->expr)
|
||||
|
@ -187,6 +187,19 @@ class TypeExpander
|
||||
$return_type->as_type = $new_as_type;
|
||||
$return_type->as = $return_type->as_type->value;
|
||||
}
|
||||
} elseif ($return_type instanceof Type\Atomic\TTemplateParam) {
|
||||
$new_as_type = self::expandUnion(
|
||||
$codebase,
|
||||
clone $return_type->as,
|
||||
$self_class,
|
||||
$static_class_type,
|
||||
$parent_class,
|
||||
$evaluate_class_constants,
|
||||
$evaluate_conditional_types,
|
||||
$final
|
||||
);
|
||||
|
||||
$return_type->as = $new_as_type;
|
||||
}
|
||||
|
||||
if ($return_type instanceof Type\Atomic\TScalarClassConstant) {
|
||||
@ -327,8 +340,9 @@ class TypeExpander
|
||||
|| $return_type instanceof Type\Atomic\TGenericObject
|
||||
|| $return_type instanceof Type\Atomic\TIterable
|
||||
) {
|
||||
foreach ($return_type->type_params as &$type_param) {
|
||||
$type_param = self::expandUnion(
|
||||
foreach ($return_type->type_params as $k => $type_param) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$return_type->type_params[$k] = self::expandUnion(
|
||||
$codebase,
|
||||
$type_param,
|
||||
$self_class,
|
||||
|
@ -461,6 +461,16 @@ class UnionTemplateHandler
|
||||
$atomic_types[] = clone $as_atomic_type;
|
||||
}
|
||||
} else {
|
||||
if ($codebase) {
|
||||
$replacement_type = TypeExpander::expandUnion(
|
||||
$codebase,
|
||||
$replacement_type,
|
||||
$calling_class,
|
||||
$calling_class,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
if ($depth < 10) {
|
||||
$replacement_type = self::replaceTemplateTypesWithStandins(
|
||||
$replacement_type,
|
||||
@ -534,6 +544,16 @@ class UnionTemplateHandler
|
||||
|
||||
$matching_input_keys = [];
|
||||
|
||||
if ($codebase) {
|
||||
$atomic_type->as = TypeExpander::expandUnion(
|
||||
$codebase,
|
||||
$atomic_type->as,
|
||||
$calling_class,
|
||||
$calling_class,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
$atomic_type->as = self::replaceTemplateTypesWithStandins(
|
||||
$atomic_type->as,
|
||||
$template_result,
|
||||
|
@ -855,6 +855,71 @@ class ConstantTest extends TestCase
|
||||
*/
|
||||
function param(int $type): void {}'
|
||||
],
|
||||
'templatedConstantInType' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T of (self::READ_UNCOMMITTED|self::READ_COMMITTED|self::REPEATABLE_READ|self::SERIALIZABLE)
|
||||
*/
|
||||
final class TransactionIsolationLevel {
|
||||
private const READ_UNCOMMITTED = \'read uncommitted\';
|
||||
private const READ_COMMITTED = \'read committed\';
|
||||
private const REPEATABLE_READ = \'repeatable read\';
|
||||
private const SERIALIZABLE = \'serializable\';
|
||||
|
||||
/**
|
||||
* @psalm-var T
|
||||
*/
|
||||
private string $level;
|
||||
|
||||
/**
|
||||
* @psalm-param T $level
|
||||
*/
|
||||
private function __construct(string $level)
|
||||
{
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return self<self::READ_UNCOMMITTED>
|
||||
*/
|
||||
public static function readUncommitted(): self
|
||||
{
|
||||
return new self(self::READ_UNCOMMITTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return self<self::READ_COMMITTED>
|
||||
*/
|
||||
public static function readCommitted(): self
|
||||
{
|
||||
return new self(self::READ_COMMITTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return self<self::REPEATABLE_READ>
|
||||
*/
|
||||
public static function repeatableRead(): self
|
||||
{
|
||||
return new self(self::REPEATABLE_READ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return self<self::SERIALIZABLE>
|
||||
*/
|
||||
public static function serializable(): self
|
||||
{
|
||||
return new self(self::SERIALIZABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return T
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user