Skip to content

Commit 178be40

Browse files
committed
feat(zend): enforce variance markers on function-origin type parameters
Signed-off-by: azjezz <azjezz@protonmail.com>
1 parent 22015f0 commit 178be40

13 files changed

Lines changed: 174 additions & 33 deletions
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Variance: +T on an arrow function in parameter position is rejected
3+
--FILE--
4+
<?php
5+
$f = fn<+T>(T $x): T => $x;
6+
?>
7+
--EXPECTF--
8+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Variance: +T on a closure in parameter position is rejected
3+
--FILE--
4+
<?php
5+
$f = function <+T>(T $x): void {};
6+
?>
7+
--EXPECTF--
8+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Variance: function-origin type parameters checked uniformly with class-origin
3+
--FILE--
4+
<?php
5+
function take<-T>(T $x): int { return 0; }
6+
function make<+T>(): T { return null; }
7+
function transform<-I, +O>(I $input): O { return null; }
8+
9+
$closure_take = function <-T>(T $x): int { return 0; };
10+
$closure_make = function <+T>(): T { return null; };
11+
$arrow_take = fn<-T>(T $x): int => 0;
12+
$arrow_make = fn<+T>(): T => null;
13+
14+
class A<+T> {
15+
public function map<-A_, +B>(A_ $a): B { return null; }
16+
}
17+
18+
take(42);
19+
make();
20+
transform(1);
21+
$closure_take(7);
22+
$closure_make();
23+
$arrow_take(7);
24+
$arrow_make();
25+
(new A)->map(42);
26+
echo "ok\n";
27+
?>
28+
--EXPECT--
29+
ok
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Variance: function-origin +T composed through Consumer<-U> in return is rejected
3+
--FILE--
4+
<?php
5+
interface Consumer<-U> { public function consume(U $x): void; }
6+
7+
function f<+T>(): Consumer<T> {}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Variance: -T on a function in return position (covariant) is rejected
3+
--FILE--
4+
<?php
5+
function f<-T>(): T {}
6+
?>
7+
--EXPECTF--
8+
Fatal error: Type parameter T declared contravariant (-T) cannot appear in covariant position in %s on line %d
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Variance: +T on a function in parameter position (contravariant) is rejected
3+
--FILE--
4+
<?php
5+
function f<+T>(T $x): void {}
6+
?>
7+
--EXPECTF--
8+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Variance: +T on a function appearing in its own bound (invariant position) is rejected
3+
--FILE--
4+
<?php
5+
interface Box<U> {}
6+
7+
function f<+T : Box<T>>(): void {}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Type parameter T declared covariant (+T) cannot appear in invariant position in %s on line %d
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Variance: +T on a method's own type parameter in parameter position is rejected
3+
--FILE--
4+
<?php
5+
class A {
6+
public function f<+T>(T $x): void {}
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Variance: class-T and function-T variance markers are checked independently in the same method
3+
--FILE--
4+
<?php
5+
class C<+T> {
6+
public function map<-A, +B>(A $a): B { return null; }
7+
}
8+
9+
(new C)->map(42);
10+
echo "ok\n";
11+
?>
12+
--EXPECT--
13+
ok
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Variance: +T on a static method's own type parameter in parameter position is rejected
3+
--FILE--
4+
<?php
5+
class A {
6+
public static function f<+T>(T $x): void {}
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Type parameter T declared covariant (+T) cannot appear in contravariant position in %s on line %d

0 commit comments

Comments
 (0)