Permalink
Browse files

Implement typed properties

RFC: https://wiki.php.net/rfc/typed_properties_v2

This is a squash of PR #3734, which is a squash of PR #3313.

Co-authored-by: Bob Weinand <bobwei9@hotmail.com>
Co-authored-by: Joe Watkins <krakjoe@php.net>
Co-authored-by: Dmitry Stogov <dmitry@zend.com>
  • Loading branch information...
4 people committed Jan 7, 2019
1 parent fe8fdfa commit e219ec144ef6682b71e135fd18654ee1bb4676b4
Showing with 23,045 additions and 5,961 deletions.
  1. +13 −1 UPGRADING
  2. +13 −0 UPGRADING.INTERNALS
  3. +44 −0 Zend/tests/type_declarations/typed_properties_001.phpt
  4. +15 −0 Zend/tests/type_declarations/typed_properties_002.phpt
  5. +15 −0 Zend/tests/type_declarations/typed_properties_003.phpt
  6. +18 −0 Zend/tests/type_declarations/typed_properties_004.phpt
  7. +20 −0 Zend/tests/type_declarations/typed_properties_005.phpt
  8. +14 −0 Zend/tests/type_declarations/typed_properties_006.phpt
  9. +17 −0 Zend/tests/type_declarations/typed_properties_007.phpt
  10. +14 −0 Zend/tests/type_declarations/typed_properties_008.phpt
  11. +23 −0 Zend/tests/type_declarations/typed_properties_009.phpt
  12. +17 −0 Zend/tests/type_declarations/typed_properties_010.phpt
  13. +18 −0 Zend/tests/type_declarations/typed_properties_011.phpt
  14. +19 −0 Zend/tests/type_declarations/typed_properties_012.phpt
  15. +10 −0 Zend/tests/type_declarations/typed_properties_013.phpt
  16. +10 −0 Zend/tests/type_declarations/typed_properties_014.phpt
  17. +10 −0 Zend/tests/type_declarations/typed_properties_015.phpt
  18. +16 −0 Zend/tests/type_declarations/typed_properties_016.phpt
  19. +12 −0 Zend/tests/type_declarations/typed_properties_017.phpt
  20. +17 −0 Zend/tests/type_declarations/typed_properties_018.phpt
  21. +22 −0 Zend/tests/type_declarations/typed_properties_019.phpt
  22. +26 −0 Zend/tests/type_declarations/typed_properties_020.phpt
  23. +15 −0 Zend/tests/type_declarations/typed_properties_021.phpt
  24. +15 −0 Zend/tests/type_declarations/typed_properties_022.phpt
  25. +52 −0 Zend/tests/type_declarations/typed_properties_023.phpt
  26. +16 −0 Zend/tests/type_declarations/typed_properties_024.phpt
  27. +11 −0 Zend/tests/type_declarations/typed_properties_025.phpt
  28. +23 −0 Zend/tests/type_declarations/typed_properties_026.phpt
  29. +16 −0 Zend/tests/type_declarations/typed_properties_027.phpt
  30. +15 −0 Zend/tests/type_declarations/typed_properties_028.phpt
  31. +18 −0 Zend/tests/type_declarations/typed_properties_029.phpt
  32. +25 −0 Zend/tests/type_declarations/typed_properties_030.phpt
  33. +22 −0 Zend/tests/type_declarations/typed_properties_031.phpt
  34. +15 −0 Zend/tests/type_declarations/typed_properties_032.phpt
  35. +38 −0 Zend/tests/type_declarations/typed_properties_033.phpt
  36. +51 −0 Zend/tests/type_declarations/typed_properties_034.phpt
  37. +13 −0 Zend/tests/type_declarations/typed_properties_035.phpt
  38. +15 −0 Zend/tests/type_declarations/typed_properties_036.phpt
  39. +16 −0 Zend/tests/type_declarations/typed_properties_037.phpt
  40. +61 −0 Zend/tests/type_declarations/typed_properties_038.phpt
  41. +31 −0 Zend/tests/type_declarations/typed_properties_039.phpt
  42. +25 −0 Zend/tests/type_declarations/typed_properties_040.phpt
  43. +16 −0 Zend/tests/type_declarations/typed_properties_041.phpt
  44. +21 −0 Zend/tests/type_declarations/typed_properties_042.phpt
  45. +53 −0 Zend/tests/type_declarations/typed_properties_043.phpt
  46. +58 −0 Zend/tests/type_declarations/typed_properties_044.phpt
  47. +51 −0 Zend/tests/type_declarations/typed_properties_045.phpt
  48. +29 −0 Zend/tests/type_declarations/typed_properties_046.phpt
  49. +40 −0 Zend/tests/type_declarations/typed_properties_047.phpt
  50. +17 −0 Zend/tests/type_declarations/typed_properties_048.phpt
  51. +10 −0 Zend/tests/type_declarations/typed_properties_049.phpt
  52. +19 −0 Zend/tests/type_declarations/typed_properties_050.phpt
  53. +27 −0 Zend/tests/type_declarations/typed_properties_051.phpt
  54. +34 −0 Zend/tests/type_declarations/typed_properties_052.phpt
  55. +12 −0 Zend/tests/type_declarations/typed_properties_053.phpt
  56. +12 −0 Zend/tests/type_declarations/typed_properties_054.phpt
  57. +29 −0 Zend/tests/type_declarations/typed_properties_055.phpt
  58. +23 −0 Zend/tests/type_declarations/typed_properties_056.phpt
  59. +31 −0 Zend/tests/type_declarations/typed_properties_057.phpt
  60. +32 −0 Zend/tests/type_declarations/typed_properties_058.phpt
  61. +29 −0 Zend/tests/type_declarations/typed_properties_059.phpt
  62. +22 −0 Zend/tests/type_declarations/typed_properties_060.phpt
  63. +58 −0 Zend/tests/type_declarations/typed_properties_061.phpt
  64. +81 −0 Zend/tests/type_declarations/typed_properties_062.phpt
  65. +80 −0 Zend/tests/type_declarations/typed_properties_063.phpt
  66. +80 −0 Zend/tests/type_declarations/typed_properties_064.phpt
  67. +71 −0 Zend/tests/type_declarations/typed_properties_065.phpt
  68. +21 −0 Zend/tests/type_declarations/typed_properties_066.phpt
  69. +36 −0 Zend/tests/type_declarations/typed_properties_067.phpt
  70. +87 −0 Zend/tests/type_declarations/typed_properties_068.phpt
  71. +27 −0 Zend/tests/type_declarations/typed_properties_069.phpt
  72. +49 −0 Zend/tests/type_declarations/typed_properties_070.phpt
  73. +36 −0 Zend/tests/type_declarations/typed_properties_071.phpt
  74. +24 −0 Zend/tests/type_declarations/typed_properties_072.phpt
  75. +44 −0 Zend/tests/type_declarations/typed_properties_073.phpt
  76. +41 −0 Zend/tests/type_declarations/typed_properties_074.phpt
  77. +53 −0 Zend/tests/type_declarations/typed_properties_075.phpt
  78. +71 −0 Zend/tests/type_declarations/typed_properties_076.phpt
  79. +18 −0 Zend/tests/type_declarations/typed_properties_077.phpt
  80. +59 −0 Zend/tests/type_declarations/typed_properties_078.phpt
  81. +33 −0 Zend/tests/type_declarations/typed_properties_079.phpt
  82. +36 −0 Zend/tests/type_declarations/typed_properties_080.phpt
  83. +22 −0 Zend/tests/type_declarations/typed_properties_081.phpt
  84. +30 −0 Zend/tests/type_declarations/typed_properties_082.phpt
  85. +80 −0 Zend/tests/type_declarations/typed_properties_083.phpt
  86. +25 −0 Zend/tests/type_declarations/typed_properties_084.phpt
  87. +17 −0 Zend/tests/type_declarations/typed_properties_085.phpt
  88. +27 −0 Zend/tests/type_declarations/typed_properties_086.phpt
  89. +15 −0 Zend/tests/type_declarations/typed_properties_087.phpt
  90. +30 −0 Zend/tests/type_declarations/typed_properties_088.phpt
  91. +38 −0 Zend/tests/type_declarations/typed_properties_089.phpt
  92. +25 −0 Zend/tests/type_declarations/typed_properties_090.phpt
  93. +199 −0 Zend/tests/type_declarations/typed_properties_091.phpt
  94. +41 −0 Zend/tests/type_declarations/typed_properties_092.phpt
  95. +31 −0 Zend/tests/type_declarations/typed_properties_093.phpt
  96. +36 −0 Zend/tests/type_declarations/typed_properties_094.phpt
  97. +84 −0 Zend/tests/type_declarations/typed_properties_095.phpt
  98. +46 −0 Zend/tests/type_declarations/typed_properties_096.phpt
  99. +90 −0 Zend/tests/type_declarations/typed_properties_097.phpt
  100. +17 −0 Zend/tests/type_declarations/typed_properties_098.phpt
  101. +20 −0 Zend/tests/type_declarations/typed_properties_099.phpt
  102. +19 −0 Zend/tests/type_declarations/typed_properties_100.phpt
  103. +37 −0 Zend/tests/type_declarations/typed_properties_101.phpt
  104. +22 −0 Zend/tests/type_declarations/typed_properties_102.phpt
  105. +23 −0 Zend/tests/type_declarations/types_in_ast.phpt
  106. +24 −0 Zend/zend.c
  107. +2 −0 Zend/zend.h
  108. +66 −13 Zend/zend_API.c
  109. +131 −0 Zend/zend_API.h
  110. +17 −1 Zend/zend_ast.c
  111. +1 −0 Zend/zend_ast.h
  112. +4 −3 Zend/zend_closures.c
  113. +195 −83 Zend/zend_compile.c
  114. +15 −2 Zend/zend_compile.h
  115. +873 −43 Zend/zend_execute.c
  116. +78 −1 Zend/zend_execute.h
  117. +116 −5 Zend/zend_inheritance.c
  118. +1 −0 Zend/zend_inheritance.h
  119. +3 −2 Zend/zend_language_parser.y
  120. +99 −19 Zend/zend_object_handlers.c
  121. +5 −3 Zend/zend_object_handlers.h
  122. +17 −1 Zend/zend_objects.c
  123. +18 −0 Zend/zend_objects_API.h
  124. +24 −0 Zend/zend_opcode.c
  125. +44 −8 Zend/zend_types.h
  126. +1 −0 Zend/zend_variables.c
  127. +640 −244 Zend/zend_vm_def.h
  128. +13,216 −2,977 Zend/zend_vm_execute.h
  129. +57 −10 Zend/zend_vm_gen.php
  130. +2,137 −1,813 Zend/zend_vm_handlers.h
  131. +32 −18 Zend/zend_vm_opcodes.c
  132. +10 −1 Zend/zend_vm_opcodes.h
  133. +2 −1 ext/com_dotnet/com_handlers.c
  134. +1 −1 ext/com_dotnet/com_saproxy.c
  135. +5 −6 ext/curl/multi.c
  136. +11 −8 ext/date/php_date.c
  137. +14 −0 ext/date/tests/DateInterval_write_property_return.phpt
  138. +4 −2 ext/dom/php_dom.c
  139. +5 −3 ext/enchant/enchant.c
  140. +6 −9 ext/exif/exif.c
  141. +3 −3 ext/ftp/php_ftp.c
  142. +10 −14 ext/intl/formatter/formatter_parse.c
  143. +5 −3 ext/intl/idn/idn.c
  144. +4 −3 ext/intl/transliterator/transliterator_class.c
  145. +44 −49 ext/ldap/ldap.c
  146. +5 −4 ext/mbstring/mbstring.c
  147. +5 −3 ext/mbstring/php_mbregex.c
  148. +4 −2 ext/mysqli/mysqli.c
  149. +11 −17 ext/mysqli/mysqli_api.c
  150. +6 −37 ext/mysqlnd/mysqlnd_ps.c
  151. +0 −1 ext/mysqlnd/mysqlnd_structs.h
  152. +12 −7 ext/oci8/oci8_interface.c
  153. +5 −4 ext/odbc/php_odbc.c
  154. +65 −47 ext/opcache/Optimizer/compact_literals.c
  155. +3 −0 ext/opcache/Optimizer/dce.c
  156. +5 −1 ext/opcache/Optimizer/escape_analysis.c
  157. +10 −1 ext/opcache/Optimizer/sccp.c
  158. +8 −1 ext/opcache/Optimizer/zend_dfg.c
  159. +13 −1 ext/opcache/Optimizer/zend_dump.c
  160. +235 −31 ext/opcache/Optimizer/zend_inference.c
  161. +45 −23 ext/opcache/Optimizer/zend_optimizer.c
  162. +16 −0 ext/opcache/Optimizer/zend_ssa.c
  163. +115 −0 ext/opcache/tests/opt/prop_types.phpt
  164. +18 −0 ext/opcache/zend_accelerator_util_funcs.c
  165. +44 −0 ext/opcache/zend_file_cache.c
  166. +34 −0 ext/opcache/zend_persist.c
  167. +20 −0 ext/opcache/zend_persist_calc.c
  168. +54 −59 ext/openssl/openssl.c
  169. +21 −29 ext/pcntl/pcntl.c
  170. +11 −12 ext/pcre/php_pcre.c
  171. +5 −3 ext/pdo/pdo_stmt.c
  172. +119 −6 ext/reflection/php_reflection.c
  173. +1 −1 ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt
  174. +39 −0 ext/reflection/tests/ReflectionClass_setStaticPropertyValue_003.phpt
  175. +113 −0 ext/reflection/tests/ReflectionProperty_isInitialized.phpt
  176. +51 −0 ext/reflection/tests/ReflectionProperty_typed_static.phpt
  177. +37 −0 ext/reflection/tests/ReflectionType_001.phpt
  178. +14 −15 ext/simplexml/simplexml.c
  179. +4 −2 ext/snmp/snmp.c
  180. +9 −5 ext/soap/soap.c
  181. +32 −53 ext/sockets/sockets.c
  182. +3 −3 ext/spl/spl_array.c
  183. +1 −1 ext/spl/tests/iterator_035.phpt
  184. +30 −18 ext/standard/array.c
  185. +3 −4 ext/standard/basic_functions.c
  186. +20 −12 ext/standard/dns.c
  187. +19 −10 ext/standard/dns_win32.c
  188. +12 −10 ext/standard/exec.c
  189. +3 −4 ext/standard/file.c
  190. +16 −20 ext/standard/fsock.c
  191. +5 −7 ext/standard/head.c
  192. +5 −3 ext/standard/image.c
  193. +2 −1 ext/standard/incomplete_class.c
  194. +6 −4 ext/standard/proc_open.c
  195. +13 −19 ext/standard/scanf.c
  196. +21 −34 ext/standard/streamsfuncs.c
  197. +11 −14 ext/standard/string.c
  198. +23 −0 ext/standard/tests/array/extract_typed_ref.phpt
  199. +28 −0 ext/standard/tests/general_functions/settype_typed_property.phpt
  200. +73 −0 ext/standard/tests/serialize/typed_property_refs.phpt
  201. +20 −15 ext/standard/type.c
  202. +51 −8 ext/standard/var.c
  203. +54 −14 ext/standard/var_unserializer.re
  204. +17 −20 ext/sysvmsg/sysvmsg.c
  205. +9 −5 ext/xml/xml.c
  206. +4 −2 ext/xmlreader/php_xmlreader.c
  207. +9 −7 ext/xmlrpc/xmlrpc-epi-php.c
  208. +31 −0 ext/zend_test/test.c
  209. +6 −10 ext/zip/php_zip.c
  210. +1 −1 tests/classes/array_access_012.phpt
@@ -78,8 +78,20 @@ PHP 7.4 UPGRADE NOTES
2. New Features
========================================

- Core:
. Added support for typed properties. For example:

class User {
public int $id;
public string $name;
}

This will enforce that $user->id can only be assigned integer and
$user->name can only be assigned strings. For more information see the
RFC: https://wiki.php.net/rfc/typed_properties_v2

- PDO_OCI:
. PDOStatement::getColumnMeta is now available
. PDOStatement::getColumnMeta() is now available

- PDO_SQLite:
. PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) allows to
@@ -13,6 +13,8 @@ PHP 7.4 INTERNALS UPGRADE NOTES
j. Removed add_get_assoc_*() and add_get_index_*()
k. Class declaration opcodes
l. HASH_FLAG_INITIALIZED
m. write_property return value
n. Assignments to references

2. Build system changes
a. Abstract
@@ -158,6 +160,17 @@ PHP 7.4 INTERNALS UPGRADE NOTES
Special HT_IS_INITIALIZED() and HT_INVALIDATE() macro were introduced
to hide implementation details.

m. The write_property() object handler now returns the assigned value (after
possible type coercions) rather than void. For extensions, it should
usually be sufficient to return whatever was passed as the argument.

n. Assignments to references now need to ensure that they respect property
types that affect the reference. This means that references should no
longer be directly assigned to, and instead a set of specialized macros
of the form ZEND_TRY_ASSIGN* needs to be used. You can find detailed
porting instructions as well as a compatibility shim in the wiki:
https://wiki.php.net/rfc/typed_properties_v2#assignments_to_references

========================
2. Build system changes
========================
@@ -0,0 +1,44 @@
--TEST--
Test typed properties basic operation
--FILE--
<?php
var_dump(new class(1, 2.2, true, ["four"], new stdClass) {
public int $int;
public float $float;
public bool $bool;
public array $array;
public stdClass $std;
public iterable $it;
public function __construct(int $int, float $float, bool $bool, array $array, stdClass $std) {
$this->int = $int;
$this->float = $float;
$this->bool = $bool;
$this->array = $array;
$this->std = $std;
$this->it = $array;
}
});
?>
--EXPECTF--
object(class@anonymous)#%d (6) {
["int"]=>
int(1)
["float"]=>
float(2.2)
["bool"]=>
bool(true)
["array"]=>
array(1) {
[0]=>
string(4) "four"
}
["std"]=>
object(stdClass)#%d (0) {
}
["it"]=>
array(1) {
[0]=>
string(4) "four"
}
}
@@ -0,0 +1,15 @@
--TEST--
Test typed properties error condition (read uninitialized)
--FILE--
<?php
$thing = new class() {
public int $int;
};
var_dump($thing->int);
?>
--EXPECTF--
Fatal error: Uncaught Error: Typed property class@anonymous::$int must not be accessed before initialization in %s:6
Stack trace:
#0 {main}
thrown in %s on line 6
@@ -0,0 +1,15 @@
--TEST--
Test typed properties error condition (fetch uninitialized by reference)
--FILE--
<?php
$thing = new class() {
public int $int;
};
$var = &$thing->int;
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access uninitialized non-nullable property class@anonymous::$int by reference in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
@@ -0,0 +1,18 @@
--TEST--
Test typed properties error condition (type mismatch)
--FILE--
<?php
new class("PHP 7 is better than you, and it knows it ...") {
public int $int;
public function __construct(string $string) {
$this->int = $string;
}
};
?>
--EXPECTF--
Fatal error: Uncaught TypeError: Typed property class@anonymous::$int must be int, string used in %s:6
Stack trace:
#0 %s(2): class@anonymous->__construct('PHP 7 is better...')
#1 {main}
thrown in %s on line 6
@@ -0,0 +1,20 @@
--TEST--
Test typed properties error condition (type mismatch object)
--FILE--
<?php
class Dummy {}
new class(new Dummy) {
public stdClass $std;
public function __construct(Dummy $dummy) {
$this->std = $dummy;
}
};
?>
--EXPECTF--
Fatal error: Uncaught TypeError: Typed property class@anonymous::$std must be an instance of stdClass, Dummy used in %s:8
Stack trace:
#0 %s(4): class@anonymous->__construct(Object(Dummy))
#1 {main}
thrown in %s on line 8
@@ -0,0 +1,14 @@
--TEST--
Test typed properties inheritance (scalar)
--FILE--
<?php
class Foo {
public int $qux;
}
class Bar extends Foo {
public string $qux;
}
?>
--EXPECTF--
Fatal error: Type of Bar::$qux must be int (as in class Foo) in %s on line 8
@@ -0,0 +1,17 @@
--TEST--
Test typed properties inheritance
--FILE--
<?php
class Whatever {}
class Thing extends Whatever {}
class Foo {
public Whatever $qux;
}
class Bar extends Foo {
public Thing $qux;
}
?>
--EXPECTF--
Fatal error: Type of Bar::$qux must be Whatever (as in class Foo) in %s on line 11
@@ -0,0 +1,14 @@
--TEST--
Test typed properties inheritance (missing info)
--FILE--
<?php
class Foo {
public int $qux;
}
class Bar extends Foo {
public $qux;
}
?>
--EXPECTF--
Fatal error: Type of Bar::$qux must be int (as in class Foo) in %s on line 8
@@ -0,0 +1,23 @@
--TEST--
Test typed properties unset leaves properties in an uninitialized state
--FILE--
<?php
class Foo {
public int $bar;
public function __get($name) {
var_dump($name);
/* return value has to be compatible with int */
return 0;
}
}
$foo = new Foo();
unset($foo->bar);
var_dump($foo->bar);
?>
--EXPECT--
string(3) "bar"
int(0)
@@ -0,0 +1,17 @@
--TEST--
Test typed properties allow fetch reference
--FILE--
<?php
class Foo {
public int $bar = 1;
}
$cb = function(int &$bar) {
var_dump($bar);
};
$foo = new Foo();
$cb($foo->bar);
?>
--EXPECT--
int(1)
@@ -0,0 +1,18 @@
--TEST--
Test typed properties allow fetch reference for init array
--FILE--
<?php
class Foo {
public int $bar = 1;
}
$foo = new Foo();
$array = [&$foo->bar];
var_dump($array);
?>
--EXPECT--
array(1) {
[0]=>
&int(1)
}
@@ -0,0 +1,19 @@
--TEST--
Test typed properties allow fetch reference for foreach
--FILE--
<?php
class Foo {
public int $bar = 1;
}
$foo = new Foo();
foreach ($foo as &$prop) {
$prop++;
}
var_dump($foo);
?>
--EXPECT--
object(Foo)#1 (1) {
["bar"]=>
&int(2)
}
@@ -0,0 +1,10 @@
--TEST--
Test typed properties disallow incorrect type initial value (scalar)
--FILE--
<?php
class Foo {
public int $bar = "string";
}
?>
--EXPECTF--
Fatal error: Default value for property of type int can only be int in %s on line 3
@@ -0,0 +1,10 @@
--TEST--
Test typed properties disallow incorrect type initial value (array)
--FILE--
<?php
class Foo {
public array $bar = 32;
}
?>
--EXPECTF--
Fatal error: Default value for property of type array can only be an array in %s on line 3
@@ -0,0 +1,10 @@
--TEST--
Test typed properties disallow incorrect type initial value (object)
--FILE--
<?php
class Foo {
public stdClass $bar = null;
}
?>
--EXPECTF--
Fatal error: Default value for property of type stdClass may not be null. Use the nullable type ?stdClass to allow null default value in %s on line %d
@@ -0,0 +1,16 @@
--TEST--
Test typed properties initial values
--FILE--
<?php
class Foo {
public int $int = 1;
public float $flt = 2.2;
public float $flt2 = 2;
public array $arr = [];
public bool $bool = false;
public iterable $iter = [];
}
echo "ok\n";
?>
--EXPECT--
ok
@@ -0,0 +1,12 @@
--TEST--
Test typed properties disallow void
--FILE--
<?php
class Foo {
public void $int;
}
$foo = new Foo();
?>
--EXPECTF--
Fatal error: Property Foo::$int cannot have type void in %s on line 3
@@ -0,0 +1,17 @@
--TEST--
Test typed properties type applies to all props in group
--FILE--
<?php
class Foo {
public int $bar,
$qux;
}
$reflector = new ReflectionClass(Foo::class);
$prop = $reflector->getProperty("qux");
var_dump((string) $prop->getType());
?>
--EXPECT--
string(3) "int"
@@ -0,0 +1,22 @@
--TEST--
Test typed properties int must not be allowed to overflow
--FILE--
<?php
class Foo {
public int $bar = PHP_INT_MAX;
public function inc() {
return ++$this->bar;
}
}
$foo = new Foo();
try {
$foo->inc();
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Cannot increment property Foo::$bar of type int past its maximal value
Oops, something went wrong.

0 comments on commit e219ec1

Please sign in to comment.