forked from phpstan/phpstan-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbug-12038.php
More file actions
94 lines (79 loc) · 1.76 KB
/
bug-12038.php
File metadata and controls
94 lines (79 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php // lint >= 8.1
declare(strict_types = 1);
namespace Bug12038;
use function PHPStan\Testing\assertType;
/**
* @template X
* @template Y
* @template Z
*
* @param callable(X, Y): Z $fn
* @return callable(Y, X): Z
*/
function flip(callable $fn): callable
{
return fn ($y, $x) => $fn($x, $y);
}
/**
* @template A
* @template B
*
* @param list<A> $fa
* @param list<B> $fb
* @return list<array{A, B}>
*/
function zip(array $fa, array $fb): array
{
$length = min(count($fa), count($fb));
$zipped = [];
for ($i = 0; $i < $length; $i++) {
$zipped[] = [$fa[$i], $fb[$i]];
}
return $zipped;
}
/**
* @template A
* @template B
* @template C
*
* @param callable(A): B $ab
* @param callable(B): C $bc
* @return callable(A): C
*/
function compose(callable $ab, callable $bc): callable
{
return fn($a) => $bc($ab($a));
}
/**
* @template T
* @param T $a
* @return list<T>
*/
function toList(mixed $a): array
{
return [$a];
}
/**
* @template V
* @param V $a
* @return array{boxed: V}
*/
function box(mixed $a): array
{
return ['boxed' => $a];
}
// flip(zip(...)) should preserve template types
$flipZip = flip(zip(...));
assertType('callable(list<B>, list<A>): list<array{A, B}>', $flipZip);
/** @var list<string> */
$strings = [];
/** @var list<int> */
$ints = [];
assertType('list<array{int, string}>', $flipZip($strings, $ints));
assertType('list<array{string, int}>', $flipZip($ints, $strings));
// compose(toList(...), box(...)) should properly unify template types
$composed1 = compose(toList(...), box(...));
assertType('callable(A): array{boxed: list<A>}', $composed1);
// compose(box(...), toList(...)) should properly unify template types
$composed2 = compose(box(...), toList(...));
assertType('callable(A): list<array{boxed: A}>', $composed2);