Skip to content
Closed
2 changes: 1 addition & 1 deletion Zend/tests/bug77530.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ echo (2)::class;

?>
--EXPECTF--
Fatal error: Illegal class name in %s on line %d
Fatal error: Cannot use ::class with dynamic class name in %s on line %d
20 changes: 20 additions & 0 deletions Zend/tests/generics/basic.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Basic generic class declaration
--FILE--
<?php

interface I<T> {
}

class C<T> {
}

final class F<T> {
}

trait T<P> {
}

?>
--EXPECT--

11 changes: 11 additions & 0 deletions Zend/tests/generics/duplicate_generic_param.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Duplicate generic parameter name
--FILE--
<?php

class Test<T, T> {
}

?>
--EXPECTF--
Fatal error: Duplicate generic parameter T in %s on line %d
73 changes: 73 additions & 0 deletions Zend/tests/generics/generic_param_with_over_types.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
--TEST--
Combining a generic parameter with other types
--FILE--
<?php

abstract class AbstractTest1<T> {
public ?T $prop;
public function method(?T $param) {
var_dump($param);
}
}
class ConcreteTest1 extends AbstractTest1<array> {}

$obj = new ConcreteTest1;
$obj->method([]);
$obj->method(null);
try {
$obj->method("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

echo "\n";

abstract class AbstractTest2<T> {
public T|int $prop;
public function method(T|int $param) {
var_dump($param);
}
}
class ConcreteTest2 extends AbstractTest2<array> {}

$obj = new ConcreteTest2;
$obj->method([]);
$obj->method(42);
$obj->method("42");

echo "\n";

abstract class AbstractTest3<T> {
public T|stdClass $prop;
public function method(T|stdClass $param) {
var_dump($param);
}
}
class ConcreteTest3 extends AbstractTest3<array> {}

$obj = new ConcreteTest3;
$obj->method([]);
$obj->method(new stdClass);
try {
$obj->method("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECTF--
array(0) {
}
NULL
Argument 1 passed to AbstractTest1::method() must be of type ?T (where T = array), string given, called in %s on line %d

array(0) {
}
int(42)
int(42)

array(0) {
}
object(stdClass)#3 (0) {
}
Argument 1 passed to AbstractTest3::method() must be of type T|stdClass (where TODO), string given, called in %s on line %d
66 changes: 66 additions & 0 deletions Zend/tests/generics/inheritance_bind_parent_param.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--TEST--
Bind direct parent parameter during inheritance
--FILE--
<?php

abstract class WithParam<T> {
public T $prop;

public function method(T $param) {
var_dump($param);
}
}

class ConcreteInt extends WithParam<int> {
}

class ConcreteStdClass extends WithParam<stdClass> {
}

class ConcreteSelf extends WithParam<self> {
}

$obj = new ConcreteInt;
$obj->method(42);
$obj->prop = 42;
var_dump($obj->prop);

try {
$obj->method("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
$obj->prop = "string";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

$obj = new ConcreteStdClass;
$obj->method(new stdClass);
//$obj->prop = new stdClass;
try {
$obj->method("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

/* TODO: This broke -- "self" resolves to WithParam here.
$obj = new ConcreteSelf;
$obj->method($obj);
try {
$obj->method(new stdClass);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
*/

?>
--EXPECTF--
int(42)
int(42)
Argument 1 passed to WithParam::method() must be of type T (where T = int), string given, called in %s on line %d
Cannot assign string to property WithParam::$prop of type T
object(stdClass)#1 (0) {
}
Argument 1 passed to WithParam::method() must be of type T (where T = stdClass), string given, called in %s on line %d
87 changes: 87 additions & 0 deletions Zend/tests/generics/inheritance_bind_parent_param_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
--TEST--
Bind multiple parent parameters during inheritance
--FILE--
<?php

abstract class WithParams<T1, T2> {
public function method(T1 $param1, T2 $param2) {
var_dump($param1);
var_dump($param2);
}
}

abstract class WithSameParam<T> extends WithParams<T, T> {
public function method2(T $param) {
var_dump($param);
}
}

abstract class WithOneFixedParam<T> extends WithParams<int, T> {
public function method2(T $param) {
var_dump($param);
}
}

abstract class WithFirstNullableParam<T> extends WithParams<?T, T> {
}

class ConcreteIntInt extends WithSameParam<int> {
}

class ConcreteIntString extends WithOneFixedParam<string> {
}

class ConcreteNullableIntInt extends WithFirstNullableParam<int> {
}

$obj = new ConcreteIntInt;
$obj->method(42, 42);
$obj->method2(42);

try {
$obj->method("string", "string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
$obj->method2("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

echo "\n";
$obj = new ConcreteIntString;
$obj->method(42, "string");
$obj->method2("string");

try {
$obj->method("string", 42);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
$obj->method2(42);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

echo "\n";
$obj = new ConcreteNullableIntInt;
$obj->method(null, 42);

?>
--EXPECTF--
int(42)
int(42)
int(42)
Argument 1 passed to WithParams::method() must be of type T1 (where T1 = int), string given, called in %s on line %d
Argument 1 passed to WithSameParam::method2() must be of type T (where T = int), string given, called in %s on line %d

int(42)
string(6) "string"
string(6) "string"
Argument 1 passed to WithParams::method() must be of type T1 (where T1 = int), string given, called in %s on line %d
string(2) "42"

NULL
int(42)
30 changes: 30 additions & 0 deletions Zend/tests/generics/inheritance_bind_passthru_parent_param.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
Bind parent parameter passed through to grandparent during inheritance
--FILE--
<?php

abstract class WithParam<T> {
public function method(T $param) {
var_dump($param);
}
}

abstract class WithParam2<T> extends WithParam<T> {
}

class Concrete extends WithParam2<int> {
}

$obj = new Concrete;
$obj->method(42);

try {
$obj->method("string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECTF--
int(42)
Argument 1 passed to WithParam::method() must be of type T (where T = int), string given, called in %s on line %d
49 changes: 49 additions & 0 deletions Zend/tests/generics/inheritance_default_param.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
--TEST--
Defaulted type parameters during inheritance
--FILE--
<?php

abstract class WithSimpleDefault<T1, T2 = int> {
public function method(T1 $param1, T2 $param2) {
var_dump($param1);
var_dump($param2);
}
}

class Concrete extends WithSimpleDefault<string> {
}

abstract class WithPrevParamDefault<T1, T2 = T1> {
public function method(T1 $param1, T2 $param2) {
var_dump($param1);
var_dump($param2);
}
}

class Concrete2 extends WithPrevParamDefault<string> {
}

$obj = new Concrete;
$obj->method("string", 42);
try {
$obj->method(42, "string");
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

$obj = new Concrete2;
$obj->method("string", "string");
try {
$obj->method([], []);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECTF--
string(6) "string"
int(42)
Argument 2 passed to WithSimpleDefault::method() must be of type T2 (where T2 = int), string given, called in %s on line %d
string(6) "string"
string(6) "string"
Argument 1 passed to WithPrevParamDefault::method() must be of type T1 (where T1 = string), array given, called in %s on line %d
16 changes: 16 additions & 0 deletions Zend/tests/generics/inheritance_signature_check.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Validating signatures involving generic parameters
--FILE--
<?php

abstract class Test<T> {
public function method(T $param) {}
}

class Test2 extends Test<int> {
public function method(string $param) {}
}

?>
--EXPECTF--
Fatal error: Declaration of Test2::method(string $param) must be compatible with Test::method(T $param) in %s on line %d
25 changes: 25 additions & 0 deletions Zend/tests/generics/inheritance_signature_check_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Validating signatures involving generic parameters
--FILE--
<?php

abstract class Test<T> {
public function method(T $param): T {}
}

class Test2 extends Test<int> {
public function method(int $param): int {}
}

class Test3<T> extends Test<T> {
public function method(T $param): T {}
}

class Test4<T> extends Test<T> {
public function method(?T $param): T {}
}

?>
===DONE===
--EXPECT--
===DONE===
Loading