Skip to content
Permalink
Browse files

Fix #2554 - treat templated class string as proper subtype of class s…

…tring
  • Loading branch information
muglug committed Jan 7, 2020
1 parent eaae84c commit 2cd7f74efbf7a352b529e5ed6e0effcdc2c24a15
Showing with 60 additions and 5 deletions.
  1. +26 −4 src/Psalm/Internal/Analyzer/TypeAnalyzer.php
  2. +34 −1 tests/Template/ClassTemplateTest.php
@@ -21,6 +21,7 @@
use Psalm\Type\Atomic\TGenericObject;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Atomic\TTemplateParamClass;
use Psalm\Type\Atomic\GetClassT;
use Psalm\Type\Atomic\GetTypeT;
use Psalm\Type\Atomic\THtmlEscapedString;
@@ -891,10 +892,21 @@ public static function isAtomicContainedBy(
if ($input_type_part instanceof GetClassT) {
$first_type = array_values($input_type_part->as_type->getAtomicTypes())[0];

$input_type_part = new TClassString(
'object',
$first_type instanceof TNamedObject ? $first_type : null
);
if ($first_type instanceof TTemplateParam) {
$object_type = array_values($first_type->as->getAtomicTypes())[0];

$input_type_part = new TTemplateParamClass(
$first_type->param_name,
$first_type->as->getId(),
$object_type instanceof TNamedObject ? $object_type : null,
$first_type->defining_class
);
} else {
$input_type_part = new TClassString(
'object',
$first_type instanceof TNamedObject ? $first_type : null
);
}
}

if ($input_type_part instanceof GetTypeT) {
@@ -1219,6 +1231,16 @@ public static function isAtomicContainedBy(
return $container_type_part->value === $input_type_part->value;
}

if ($container_type_part instanceof TTemplateParamClass
&& get_class($input_type_part) === TClassString::class
) {
if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced = true;
}

return false;
}

if ($container_type_part instanceof TClassString
&& $container_type_part->as === 'object'
&& !$container_type_part->as_type
@@ -2241,7 +2241,40 @@ function(AccessInterceptorInterface $i) : string {
}
);
}'
]
],
'assertionOnTemplatedClassString' => [
'<?php
class TEM {
/**
* @template Entity
* @psalm-param class-string<Entity> $type
* @psalm-return EQB<Entity>
*/
public function createEQB(string $type) {
if (!class_exists($type)) {
throw new InvalidArgumentException();
}
return new EQB($type);
}
}
/**
* @template Entity
*/
class EQB {
/**
* @psalm-var class-string<Entity>
*/
protected $type;
/**
* @psalm-param class-string<Entity> $type
*/
public function __construct(string $type) {
$this->type = $type;
}
}'
],
];
}

0 comments on commit 2cd7f74

Please sign in to comment.
You can’t perform that action at this time.