1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Prevent template params leaking when extended

This commit is contained in:
Brown 2019-01-10 10:27:40 -05:00
parent e23d5a9e79
commit 1e20cbfa79
2 changed files with 70 additions and 8 deletions

View File

@ -913,11 +913,11 @@ class Union
$is_mixed = false;
foreach ($this->types as $key => $atomic_type) {
if ($atomic_type instanceof Type\Atomic\TGenericParam
&& isset($template_types[$key])
) {
if ($atomic_type instanceof Type\Atomic\TGenericParam) {
$keys_to_unset[] = $key;
$template_type = clone $template_types[$key];
$template_type = isset($template_types[$key])
? clone $template_types[$key]
: Type::getMixed();
foreach ($template_type->types as $template_type_part) {
if ($template_type_part instanceof Type\Atomic\TMixed) {
@ -926,11 +926,11 @@ class Union
$new_types[$template_type_part->getKey()] = $template_type_part;
}
} elseif ($atomic_type instanceof Type\Atomic\TGenericParamClass
&& isset($template_types[$atomic_type->param_name])
) {
} elseif ($atomic_type instanceof Type\Atomic\TGenericParamClass) {
$keys_to_unset[] = $key;
$template_type = clone $template_types[$atomic_type->param_name];
$template_type = isset($template_types[$atomic_type->param_name])
? clone $template_types[$atomic_type->param_name]
: Type::getMixed();
foreach ($template_type->types as $template_type_part) {
if ($template_type_part instanceof Type\Atomic\TMixed) {

View File

@ -1274,6 +1274,68 @@ class TemplateTest extends TestCase
if ($val) {}
}',
],
'mixedTemplatedParamOutWithNoTemplateExtends' => [
'<?php
/**
* @template TValue
*/
class ValueContainer
{
/**
* @var TValue
*/
private $v;
/**
* @param TValue $v
*/
public function __construct($v)
{
$this->v = $v;
}
/**
* @return TValue
*/
public function getValue()
{
return $this->v;
}
}
/**
* @template TKey
* @template Tv
*/
class KeyValueContainer extends ValueContainer
{
/**
* @var TKey
*/
private $k;
/**
* @param TKey $k
* @param Tv $v
*/
public function __construct($k, $v)
{
$this->k = $k;
parent::__construct($v);
}
/**
* @return TKey
*/
public function getKey()
{
return $this->k;
}
}
$a = new KeyValueContainer("hello", 15);
$b = $a->getValue();',
[
'$a' => 'KeyValueContainer<string, int>',
'$b' => 'mixed',
],
'error_levels' => ['MixedAssignment'],
],
];
}