Skip to content

Commit db84adf

Browse files
committed
Compile time generics W.I.P.
1 parent 67cbe09 commit db84adf

59 files changed

Lines changed: 1761 additions & 78 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Abstract generic types basic
3+
--FILE--
4+
<?php
5+
6+
interface I<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
class CS implements I<string> {
11+
public function foo(string $param): string {
12+
return $param . '!';
13+
}
14+
}
15+
16+
class CI implements I<int> {
17+
public function foo(int $param): int {
18+
return $param + 42;
19+
}
20+
}
21+
22+
$cs = new CS();
23+
var_dump($cs->foo("Hello"));
24+
25+
$ci = new CI();
26+
var_dump($ci->foo(5));
27+
28+
?>
29+
--EXPECT--
30+
string(6) "Hello!"
31+
int(47)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--TEST--
2+
Concrete example of using AT
3+
--CREDITS--
4+
Levi Morrison
5+
--FILE--
6+
<?php declare(strict_types=1);
7+
8+
namespace Sequence;
9+
10+
// No null. This is probably going to be painful, but let's try it.
11+
interface Sequence<Item : object|array|string|float|int|bool>
12+
{
13+
function next(): ?Item;
14+
15+
/**
16+
* @param callable(Item, Item): Item $f
17+
* @return ?Item
18+
*/
19+
function reduce(callable $f): ?Item;
20+
}
21+
22+
final class StringTablePair
23+
{
24+
public function __construct(
25+
public readonly string $string,
26+
public readonly int $id,
27+
) {}
28+
}
29+
30+
final class StringTableSequence implements Sequence<StringTablePair>
31+
{
32+
private array $strings;
33+
34+
public function __construct(StringTable $string_table) {
35+
$this->strings = $string_table->to_assoc_array();
36+
}
37+
38+
function next(): ?StringTablePair
39+
{
40+
$key = \array_key_first($this->strings);
41+
if (!isset($key)) {
42+
return null;
43+
}
44+
$value = \array_shift($this->strings);
45+
return new StringTablePair($key, $value);
46+
}
47+
48+
/**
49+
* @param callable(Item, Item): Item $f
50+
* @return ?Item
51+
*/
52+
function reduce(callable $f): ?StringTablePair
53+
{
54+
$reduction = $this->next();
55+
if (!isset($reduction)) {
56+
return null;
57+
}
58+
59+
while (($next = $this->next()) !== null) {
60+
$reduction = $f($reduction, $next);
61+
}
62+
return $reduction;
63+
}
64+
}
65+
66+
final class StringTable
67+
{
68+
private array $strings = ["" => 0];
69+
70+
public function __construct() {}
71+
72+
public function offsetGet(string $offset): int
73+
{
74+
return $this->strings[$offset] ?? throw new \Exception();
75+
}
76+
77+
public function offsetExists(string $offset): bool
78+
{
79+
return \isset($this->strings[$offset]);
80+
}
81+
82+
public function intern(string $str): int
83+
{
84+
return $this->strings[$str]
85+
?? ($this->strings[$str] = \count($this->strings));
86+
}
87+
88+
public function to_sequence(): StringTableSequence
89+
{
90+
return new StringTableSequence($this);
91+
}
92+
93+
public function to_assoc_array(): array {
94+
return $this->strings;
95+
}
96+
}
97+
98+
?>
99+
--EXPECTF--
100+
Fatal error: Generic type cannot be part of a union type in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance with different bound types
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2<T> extends I1<T> {
11+
public function bar(int $o, T $param): T;
12+
}
13+
14+
class C implements I2<float>, I1<string> {
15+
public function foo(float $param): float {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Bound type T for interface I1 implemented explicitly in C with type string must match the implicitly bound type float from interface I2 in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance with different bound types 2
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2<T> extends I1<T> {
11+
public function bar(int $o, T $param): T;
12+
}
13+
14+
class C implements I1<string>, I2<float> {
15+
public function foo(string $param): string {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Bound type T for interface I1 implemented explicitly in C with type string must match the implicitly bound type float from interface I2 in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance with different bound types 3
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2 extends I1<float> {
11+
public function bar(int $o, float $param): float;
12+
}
13+
14+
class C implements I2, I1<string> {
15+
public function foo(float $param): float {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Bound type T for interface I1 implemented explicitly in C with type string must match the implicitly bound type float from interface I2 in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance with different bound types 4
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2 extends I1<float> {
11+
public function bar(int $o, float $param): float;
12+
}
13+
14+
class C implements I1<string>, I2 {
15+
public function foo(string $param): string {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Bound type T for interface I1 implemented explicitly in C with type string must match the implicitly bound type float from interface I2 in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance missing bound types
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2<T> extends I1<T> {
11+
public function bar(int $o, T $param): T;
12+
}
13+
14+
class C implements I2<float>, I1 {
15+
public function foo(float $param): float {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Interface I1 expects 1 generic parameters, 0 given in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance missing bound types 2
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2<T> extends I1<T> {
11+
public function bar(int $o, T $param): T;
12+
}
13+
14+
class C implements I1, I2<float> {
15+
public function foo(float $param): float {}
16+
public function bar(int $o, float $param): float {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Interface I1 expects 1 generic parameters, 0 given in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance missing bound types 3
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2 extends I1<string> {
11+
public function bar(int $o, string $param): string;
12+
}
13+
14+
class C implements I1, I2 {
15+
public function foo(string $param): string {}
16+
public function bar(int $o, string $param): string {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Interface I1 expects 1 generic parameters, 0 given in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Implicit interface inheritance missing bound types 4
3+
--FILE--
4+
<?php
5+
6+
interface I1<T> {
7+
public function foo(T $param): T;
8+
}
9+
10+
interface I2 extends I1<string> {
11+
public function bar(int $o, string $param): string;
12+
}
13+
14+
class C implements I2, I1 {
15+
public function foo(string $param): string {}
16+
public function bar(int $o, string $param): string {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Interface I1 expects 1 generic parameters, 0 given in %s on line %d

0 commit comments

Comments
 (0)