Skip to content

Commit

Permalink
Fix #2771 - replace empty params with generic equivalents
Browse files Browse the repository at this point in the history
Ref #2755
  • Loading branch information
muglug committed Feb 8, 2020
1 parent d99f23e commit b26deb4
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 22 deletions.
10 changes: 10 additions & 0 deletions src/Psalm/Internal/Analyzer/TypeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2014,6 +2014,16 @@ private static function isMatchingTypeContainedBy(
$container_param = $container_type_part->type_params[$i];

if ($input_param->isEmpty()) {
if (!$atomic_comparison_result->replacement_atomic_type) {
$atomic_comparison_result->replacement_atomic_type = clone $input_type_part;
}

if ($atomic_comparison_result->replacement_atomic_type instanceof TGenericObject) {
/** @psalm-suppress PropertyTypeCoercion */
$atomic_comparison_result->replacement_atomic_type->type_params[$i]
= clone $container_param;
}

continue;
}

Expand Down
143 changes: 121 additions & 22 deletions tests/Template/ClassTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ public function __construct(array $data) {
* @return ArrayCollection<TKey,T>
*/
public function map(Closure $func) {
return new static(array_map($func, $this->data));
return new static(array_map($func, $this->data));
}
}
Expand Down Expand Up @@ -428,13 +428,13 @@ class I {}
$c = new Collection;
$c->filter(
/** @param Collection<mixed,I> $elt */
function(Collection $elt): bool { return (bool) rand(0,1); }
/** @param Collection<mixed,I> $elt */
function(Collection $elt): bool { return (bool) rand(0,1); }
);
$c->filter(
/** @param Collection<mixed,I> $elt */
function(Collection $elt): bool { return true; }
/** @param Collection<mixed,I> $elt */
function(Collection $elt): bool { return true; }
);',
],
'templatedInterfaceIteration' => [
Expand Down Expand Up @@ -1128,8 +1128,8 @@ class Converter
public $records;
/**
* @param array<I, V> $records
*/
* @param array<I, V> $records
*/
public function __construct(array $records) {
$this->records = $records;
}
Expand All @@ -1146,7 +1146,7 @@ private function appender(object $obj2): array
$arr = [];
foreach ($this->records as $key => $obj) {
if (rand(0, 1)) {
$obj = $obj2;
$obj = $obj2;
}
$arr[$key] = $obj;
}
Expand Down Expand Up @@ -1211,7 +1211,7 @@ private function appender(string $obj2): array
$arr = [];
foreach ($this->records as $key => $obj) {
if (rand(0, 1)) {
$obj = new $obj2;
$obj = new $obj2;
}
$arr[$key] = $obj;
}
Expand Down Expand Up @@ -1852,23 +1852,22 @@ public function __construct($closure) {}
class Bar
{
/** @var Foo<array> */
private $FooArray;
/** @var Foo<array> */
private $FooArray;
public function __construct()
{
$this->FooArray = new Foo(function(string $s): array {
/** @psalm-suppress MixedAssignment */
$json = \json_decode($s, true);
public function __construct() {
$this->FooArray = new Foo(function(string $s): array {
/** @psalm-suppress MixedAssignment */
$json = \json_decode($s, true);
if (! \is_array($json)) {
return [];
}
if (! \is_array($json)) {
return [];
}
return $json;
});
return $json;
});
takesFooArray($this->FooArray);
takesFooArray($this->FooArray);
}
}
Expand Down Expand Up @@ -2275,6 +2274,55 @@ public function __construct(string $type) {
}
}'
],
'newGenericBecomesPropertyType' => [
'<?php
class B {}
class A {
/** @var ArrayCollection<int, B> */
public ArrayCollection $b_collection;
public function __construct() {
$this->b_collection = new ArrayCollection([]);
$this->b_collection->add(5, new B());
}
}
/**
* @psalm-template TKey
* @psalm-template T
*/
class ArrayCollection
{
/**
* An array containing the entries of this collection.
*
* @psalm-var array<TKey,T>
* @var array
*/
private $elements = [];
/**
* Initializes a new ArrayCollection.
*
* @param array $elements
*
* @psalm-param array<TKey,T> $elements
*/
public function __construct(array $elements = [])
{
$this->elements = $elements;
}
/**
* @param TKey $key
* @param T $t
*/
public function add($key, $t) : void {
$this->elements[$key] = $t;
}
}'
],
];
}

Expand Down Expand Up @@ -2722,6 +2770,57 @@ public static function foo($t) : void {}
}',
'error_message' => 'UndefinedDocblockClass'
],
'newGenericBecomesPropertyType' => [
'<?php
class B {}
class C {}
class A {
/** @var ArrayCollection<int, B> */
public ArrayCollection $b_collection;
public function __construct() {
$this->b_collection = new ArrayCollection([]);
$this->b_collection->add(5, new C());
}
}
/**
* @psalm-template TKey
* @psalm-template T
*/
class ArrayCollection
{
/**
* An array containing the entries of this collection.
*
* @psalm-var array<TKey,T>
* @var array
*/
private $elements = [];
/**
* Initializes a new ArrayCollection.
*
* @param array $elements
*
* @psalm-param array<TKey,T> $elements
*/
public function __construct(array $elements = [])
{
$this->elements = $elements;
}
/**
* @param TKey $key
* @param T $t
*/
public function add($key, $t) : void {
$this->elements[$key] = $t;
}
}',
'error_message' => 'InvalidArgument'
],
];
}
}

0 comments on commit b26deb4

Please sign in to comment.