mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Improve handling of default extended params
This commit is contained in:
parent
70b8df268d
commit
b693b726c7
@ -145,6 +145,7 @@ class TypeAnalyzer
|
||||
|
||||
if ($input_type_part instanceof TMixed
|
||||
&& $input_type->from_template_default
|
||||
&& $input_type->from_docblock
|
||||
&& $atomic_comparison_result
|
||||
&& $atomic_comparison_result->type_coerced_from_mixed
|
||||
) {
|
||||
@ -250,7 +251,9 @@ class TypeAnalyzer
|
||||
if ($all_type_coerced_from_mixed) {
|
||||
$union_comparison_result->type_coerced_from_mixed = true;
|
||||
|
||||
if ($input_type->from_template_default || $all_type_coerced_from_as_mixed) {
|
||||
if (($input_type->from_template_default && $input_type->from_docblock)
|
||||
|| $all_type_coerced_from_as_mixed
|
||||
) {
|
||||
$union_comparison_result->type_coerced_from_as_mixed = true;
|
||||
}
|
||||
}
|
||||
@ -265,7 +268,9 @@ class TypeAnalyzer
|
||||
if ($some_type_coerced_from_mixed) {
|
||||
$union_comparison_result->type_coerced_from_mixed = true;
|
||||
|
||||
if ($input_type->from_template_default || $all_type_coerced_from_as_mixed) {
|
||||
if (($input_type->from_template_default && $input_type->from_docblock)
|
||||
|| $all_type_coerced_from_as_mixed
|
||||
) {
|
||||
$union_comparison_result->type_coerced_from_as_mixed = true;
|
||||
}
|
||||
}
|
||||
|
@ -403,8 +403,10 @@ class Populator
|
||||
|
||||
foreach ($trait_storage->template_types as $template_name => $template_type_map) {
|
||||
foreach ($template_type_map as $template_type) {
|
||||
$default_param = clone $template_type[0];
|
||||
$default_param->from_docblock = false;
|
||||
$storage->template_type_extends[$trait_storage->name][$template_name]
|
||||
= $template_type[0];
|
||||
= $default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -517,8 +519,10 @@ class Populator
|
||||
|
||||
foreach ($parent_storage->template_types as $template_name => $template_type_map) {
|
||||
foreach ($template_type_map as $template_type) {
|
||||
$default_param = clone $template_type[0];
|
||||
$default_param->from_docblock = false;
|
||||
$storage->template_type_extends[$parent_storage->name][$template_name]
|
||||
= $template_type[0];
|
||||
= $default_param;
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,8 +659,10 @@ class Populator
|
||||
|
||||
foreach ($parent_interface_storage->template_types as $template_name => $template_type_map) {
|
||||
foreach ($template_type_map as $template_type) {
|
||||
$default_param = clone $template_type[0];
|
||||
$default_param->from_docblock = false;
|
||||
$storage->template_type_extends[$parent_interface_storage->name][$template_name]
|
||||
= $template_type[0];
|
||||
= $default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -747,8 +753,10 @@ class Populator
|
||||
|
||||
foreach ($implemented_interface_storage->template_types as $template_name => $template_type_map) {
|
||||
foreach ($template_type_map as $template_type) {
|
||||
$default_param = clone $template_type[0];
|
||||
$default_param->from_docblock = false;
|
||||
$storage->template_type_extends[$implemented_interface_storage->name][$template_name]
|
||||
= $template_type[0];
|
||||
= $default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +321,64 @@ class ClassTemplateCovarianceTest extends TestCase
|
||||
class CovariantFoo extends InvariantFoo {}',
|
||||
'error_message' => 'InvalidTemplateParam',
|
||||
],
|
||||
'expectsTemplatedObject' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
* @template-implements ArrayAccess<int,T>
|
||||
*/
|
||||
class MyArray implements ArrayAccess, IteratorAggregate {
|
||||
/** @var array<int,T> */
|
||||
private $values = [];
|
||||
public function __construct() {
|
||||
$this->values = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param T $value
|
||||
*/
|
||||
public function offsetSet($offset, $value) {
|
||||
$this->values[$offset] = $value;
|
||||
}
|
||||
/**
|
||||
* @param int $offset
|
||||
* @return T
|
||||
*/
|
||||
public function offsetGet($offset) {
|
||||
return $this->values[$offset];
|
||||
}
|
||||
/**
|
||||
* @param int $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset) {
|
||||
return isset($this->values[$offset]);
|
||||
}
|
||||
/**
|
||||
* @param int $offset
|
||||
*/
|
||||
public function offsetUnset($offset) {
|
||||
unset($this->values[$offset]);
|
||||
}
|
||||
|
||||
public function getIterator() : Traversable {
|
||||
return new ArrayObject($this->values);
|
||||
}
|
||||
}
|
||||
|
||||
class A {}
|
||||
class AChild extends A {}
|
||||
|
||||
/** @param IteratorAggregate<int, A> $i */
|
||||
function expectsIteratorAggregateOfA(IteratorAggregate $i) : void {}
|
||||
|
||||
/** @param MyArray<AChild> $m */
|
||||
function takesMyArrayOfAChild(MyArray $m) : void {
|
||||
expectsIteratorAggregateOfA($m);
|
||||
}',
|
||||
'error_message' => 'MixedArgumentTypeCoercion',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user