Browse Source
Implement object type annotation
Implement object type annotation
RFC: https://wiki.php.net/rfc/object-typehintpull/2595/merge
committed by
Nikita Popov
24 changed files with 363 additions and 116 deletions
-
1NEWS
-
3UPGRADING
-
8Zend/tests/bug26698.phpt
-
12Zend/tests/bug28444.phpt
-
4Zend/tests/bug60598.phpt
-
10Zend/tests/object_types/invalid_default_value.phpt
-
15Zend/tests/object_types/missing_return_type_inheritance_in_class.phpt
-
15Zend/tests/object_types/missing_return_type_inheritance_in_interface.phpt
-
26Zend/tests/object_types/return_type_in_class.phpt
-
16Zend/tests/object_types/return_type_in_function.phpt
-
26Zend/tests/object_types/return_type_inheritance_in_class.phpt
-
26Zend/tests/object_types/return_type_inheritance_in_interface.phpt
-
31Zend/tests/object_types/return_type_reflection.phpt
-
19Zend/tests/object_types/type_hint_in_class_method.phpt
-
17Zend/tests/object_types/type_hint_in_function.phpt
-
31Zend/tests/object_types/type_hint_reflection.phpt
-
8Zend/zend_compile.c
-
5Zend/zend_execute.c
-
4ext/reflection/tests/bug38194.phpt
-
14ext/reflection/tests/bug38217.phpt
-
80tests/classes/array_access_001.phpt
-
80tests/classes/array_access_002.phpt
-
14tests/classes/array_access_003.phpt
-
14tests/classes/array_access_004.phpt
@ -0,0 +1,10 @@ |
|||
--TEST-- |
|||
Object type can only default to null |
|||
--FILE-- |
|||
<?php |
|||
|
|||
function test(object $obj = 42) { } |
|||
|
|||
?> |
|||
--EXPECTF-- |
|||
Fatal error: Default value for parameters with a object type can only be NULL in %s on line %d |
|||
@ -0,0 +1,15 @@ |
|||
--TEST-- |
|||
Missing class method a object return type during inheritance |
|||
--FILE-- |
|||
<?php |
|||
|
|||
class One { |
|||
public function a() : object {} |
|||
} |
|||
|
|||
class Two extends One { |
|||
public function a() {} |
|||
} |
|||
|
|||
--EXPECTF-- |
|||
Fatal error: Declaration of Two::a() must be compatible with One::a(): object in %s on line 9 |
|||
@ -0,0 +1,15 @@ |
|||
--TEST-- |
|||
Missing interface method a object return type during inheritance |
|||
--FILE-- |
|||
<?php |
|||
|
|||
interface One { |
|||
public function a() : object; |
|||
} |
|||
|
|||
interface Two extends One { |
|||
public function a(); |
|||
} |
|||
|
|||
--EXPECTF-- |
|||
Fatal error: Declaration of Two::a() must be compatible with One::a(): object in %s on line %d |
|||
@ -0,0 +1,26 @@ |
|||
--TEST-- |
|||
Adding a class method object return type |
|||
--FILE-- |
|||
<?php |
|||
|
|||
interface One { |
|||
public function a() : object; |
|||
} |
|||
|
|||
class Two implements One { |
|||
public function a() : object {} |
|||
} |
|||
|
|||
$three = new class extends Two { |
|||
public function a() : object { |
|||
return 12345; |
|||
} |
|||
}; |
|||
$three->a(); |
|||
--EXPECTF-- |
|||
|
|||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13 |
|||
Stack trace: |
|||
#0 %s(16): class@anonymous->a() |
|||
#1 {main} |
|||
thrown in %s on line 13 |
|||
@ -0,0 +1,16 @@ |
|||
--TEST-- |
|||
Adding a function object return type |
|||
--FILE-- |
|||
<?php |
|||
|
|||
function a() : object { |
|||
return 12345; |
|||
} |
|||
a(); |
|||
--EXPECTF-- |
|||
|
|||
Fatal error: Uncaught TypeError: Return value of a() must be an object, integer returned in %s:4 |
|||
Stack trace: |
|||
#0 %s(6): a() |
|||
#1 {main} |
|||
thrown in %s on line 4 |
|||
@ -0,0 +1,26 @@ |
|||
--TEST-- |
|||
Adding class method a object return type during inheritance is allowed |
|||
--FILE-- |
|||
<?php |
|||
|
|||
class One { |
|||
public function a() {} |
|||
} |
|||
|
|||
class Two extends One { |
|||
public function a() : object {} |
|||
} |
|||
|
|||
$three = new class extends Two { |
|||
public function a() : object { |
|||
return 12345; |
|||
} |
|||
}; |
|||
$three->a(); |
|||
|
|||
--EXPECTF-- |
|||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13 |
|||
Stack trace: |
|||
#0 %s(16): class@anonymous->a() |
|||
#1 {main} |
|||
thrown in /%s on line 13 |
|||
@ -0,0 +1,26 @@ |
|||
--TEST-- |
|||
Adding interface method a object return type during inheritance is allowed |
|||
--FILE-- |
|||
<?php |
|||
|
|||
interface One { |
|||
public function a(); |
|||
} |
|||
|
|||
interface Two extends One { |
|||
public function a() : object; |
|||
} |
|||
|
|||
$three = new class implements Two { |
|||
public function a() : object { |
|||
return 12345; |
|||
} |
|||
}; |
|||
$three->a(); |
|||
|
|||
--EXPECTF-- |
|||
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, integer returned in %s:13 |
|||
Stack trace: |
|||
#0 %s(16): class@anonymous->a() |
|||
#1 {main} |
|||
thrown in /%s on line 13 |
|||
@ -0,0 +1,31 @@ |
|||
--TEST-- |
|||
Reflecting object return type |
|||
--FILE-- |
|||
<?php |
|||
|
|||
interface One { |
|||
public function a() : object; |
|||
} |
|||
|
|||
class Two implements One { |
|||
public function a() : object {} |
|||
} |
|||
|
|||
function a() : object {} |
|||
|
|||
$returnTypeOne = (new ReflectionClass(One::class))->getMethod('a')->getReturnType(); |
|||
var_dump($returnTypeOne->isBuiltin(), (string)$returnTypeOne); |
|||
|
|||
$returnTypeTwo = (new ReflectionClass(Two::class))->getMethod('a')->getReturnType(); |
|||
var_dump($returnTypeTwo->isBuiltin(), (string)$returnTypeTwo); |
|||
|
|||
$returnTypea = (new ReflectionFunction('a'))->getReturnType(); |
|||
var_dump($returnTypea->isBuiltin(), (string)$returnTypea); |
|||
|
|||
--EXPECTF-- |
|||
bool(true) |
|||
string(6) "object" |
|||
bool(true) |
|||
string(6) "object" |
|||
bool(true) |
|||
string(6) "object" |
|||
@ -0,0 +1,19 @@ |
|||
--TEST-- |
|||
Adding a class method object type hint |
|||
--FILE-- |
|||
<?php |
|||
|
|||
class One { |
|||
public function a(object $obj) {} |
|||
} |
|||
|
|||
$one = new One(); |
|||
$one->a(new One()); |
|||
$one->a(123); |
|||
--EXPECTF-- |
|||
|
|||
Fatal error: Uncaught TypeError: Argument 1 passed to One::a() must be an object, integer given, called in %s:4 |
|||
Stack trace: |
|||
#0 %s(9): One->a(123) |
|||
#1 {main} |
|||
thrown in %s on line 4 |
|||
@ -0,0 +1,17 @@ |
|||
--TEST-- |
|||
Adding a function object type hint |
|||
--FILE-- |
|||
<?php |
|||
|
|||
class A {} |
|||
function a(object $obj) {} |
|||
|
|||
a(new A()); |
|||
a(123); |
|||
--EXPECTF-- |
|||
|
|||
Fatal error: Uncaught TypeError: Argument 1 passed to a() must be an object, integer given, called in %s.php on line 7 and defined in %s:4 |
|||
Stack trace: |
|||
#0 %s(7): a(123) |
|||
#1 {main} |
|||
thrown in %s on line 4 |
|||
@ -0,0 +1,31 @@ |
|||
--TEST-- |
|||
Reflecting object type hint |
|||
--FILE-- |
|||
<?php |
|||
|
|||
interface One { |
|||
public function a(object $obj); |
|||
} |
|||
|
|||
class Two implements One { |
|||
public function a(object $obj) {} |
|||
} |
|||
|
|||
function a(object $obj) {} |
|||
|
|||
$typeHintOne = (new ReflectionClass(One::class))->getMethod('a')->getParameters()[0]->getType(); |
|||
var_dump($typeHintOne->isBuiltin(), (string)$typeHintOne); |
|||
|
|||
$typeHintTwo = (new ReflectionClass(Two::class))->getMethod('a')->getParameters()[0]->getType(); |
|||
var_dump($typeHintTwo->isBuiltin(), (string)$typeHintTwo); |
|||
|
|||
$typeHinta = (new ReflectionFunction('a'))->getParameters()[0]->getType(); |
|||
var_dump($typeHinta->isBuiltin(), (string)$typeHinta); |
|||
|
|||
--EXPECTF-- |
|||
bool(true) |
|||
string(6) "object" |
|||
bool(true) |
|||
string(6) "object" |
|||
bool(true) |
|||
string(6) "object" |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue