Skip to content

Commit 8b0d61a

Browse files
committed
Regression tests
Closes phpstan/phpstan#12355 Closes phpstan/phpstan#9828
1 parent c71be49 commit 8b0d61a

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Bug12355;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @phpstan-type AnimalData array{
9+
* animalSpecificData: ValidType,
10+
* habitat?: string,
11+
* }
12+
* @template ValidType of array{
13+
* name: string,
14+
* ...,
15+
* }
16+
*/
17+
abstract class Animal
18+
{
19+
/**
20+
* @param AnimalData $arg
21+
*/
22+
public function __construct(array $arg) {
23+
assertType('ValidType of array{name: string} (class Bug12355\Animal, argument)', $arg['animalSpecificData']);
24+
if (isset($arg['habitat'])) {
25+
//do things
26+
}
27+
assertType('ValidType of array{name: string} (class Bug12355\Animal, argument)', $arg['animalSpecificData']);
28+
}
29+
}
30+
31+
/**
32+
* @template T of array{name: string, ...}
33+
* @param array{first: T, second: T, flag?: bool} $arg
34+
*/
35+
function testMergeWithDifferentObjects(array $arg): void
36+
{
37+
assertType('T of array{name: string} (function Bug12355\testMergeWithDifferentObjects(), argument)', $arg['first']);
38+
39+
// Modifying $arg in one branch causes different ConstantArrayType objects
40+
if (isset($arg['flag'])) {
41+
$arg['extra'] = true;
42+
}
43+
44+
// After scope merge, $arg's value types for 'first' and 'second' go through
45+
// ConstantArrayType::mergeWith() which uses new self() — stripping TemplateConstantArrayType
46+
assertType('T of array{name: string} (function Bug12355\testMergeWithDifferentObjects(), argument)', $arg['first']);
47+
assertType('T of array{name: string} (function Bug12355\testMergeWithDifferentObjects(), argument)', $arg['second']);
48+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Bug9828;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @template T of array{value: int, ...}
9+
* @param array<int, T> $array
10+
* @return array<int, T>
11+
*/
12+
function filter(array $array, int $min_value): array
13+
{
14+
foreach ($array as $key => $row) {
15+
if ($row['value'] < $min_value) unset($array[$key]);
16+
}
17+
return array_values($array);
18+
}
19+
20+
/**
21+
* @template T of array{value: int, ...}
22+
* @param array<int, T> $array
23+
* @return list<T>
24+
*/
25+
function filter2(array $array, int $min_value): array
26+
{
27+
$result = [];
28+
foreach ($array as $row) {
29+
if ($row['value'] >= $min_value) $result[] = $row;
30+
}
31+
return $result;
32+
}
33+
34+
/**
35+
* @param array<int, array{value: int, name: string}> $data
36+
*/
37+
function test(array $data): void
38+
{
39+
assertType('array<int, array{value: int, name: string}>', filter($data, 5));
40+
assertType('list<array{value: int, name: string}>', filter2($data, 5));
41+
}

0 commit comments

Comments
 (0)