From 8a7c322579d7649d780be98ac0a5c0df5f72c382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 28 Apr 2020 11:40:32 +0200 Subject: [PATCH] Add support for the number and scalar types --- .../number/casting/number_cast_error.phpt | 10 +++ .../number_parameter_inheritance_error1.phpt | 18 ++++++ ...number_parameter_inheritance_success1.phpt | 17 +++++ ...number_parameter_inheritance_success2.phpt | 22 +++++++ ...number_parameter_inheritance_success3.phpt | 17 +++++ ...number_parameter_inheritance_success4.phpt | 17 +++++ .../number_property_inheritance_error1.phpt | 18 ++++++ .../number_property_inheritance_error2.phpt | 18 ++++++ .../number_property_inheritance_error3.phpt | 18 ++++++ .../number_return_inheritance_error1.phpt | 18 ++++++ .../number_return_inheritance_error2.phpt | 18 ++++++ .../number_return_inheritance_success1.phpt | 22 +++++++ .../number_return_inheritance_success2.phpt | 22 +++++++ .../nullable_number_parameter_success.phpt | 11 ++++ .../nullable_number_property_success.phpt | 12 ++++ .../nullable_number_return_success.phpt | 11 ++++ .../number/syntax/number_parameter_error.phpt | 12 ++++ .../syntax/number_parameter_success.phpt | 11 ++++ .../number/syntax/number_return_error.phpt | 12 ++++ .../number/syntax/number_return_success.phpt | 11 ++++ .../syntax/number_void_return_error.phpt | 12 ++++ .../number_parameter_strict_error.phpt | 47 ++++++++++++++ .../number_parameter_strict_success.phpt | 18 ++++++ .../number_parameter_weak_error.phpt | 39 ++++++++++++ .../number_parameter_weak_success.phpt | 27 ++++++++ .../number_property_strict_error1.phpt | 14 +++++ .../number_property_strict_error2.phpt | 14 +++++ .../number_property_strict_error3.phpt | 14 +++++ .../number_property_strict_error4.phpt | 14 +++++ .../number_property_strict_error5.phpt | 14 +++++ .../number_property_strict_error6.phpt | 25 ++++++++ .../number_property_strict_error7.phpt | 25 ++++++++ .../number_property_strict_success.phpt | 16 +++++ .../number_property_weak_error1.phpt | 15 +++++ .../number_property_weak_error2.phpt | 15 +++++ .../number_property_weak_error3.phpt | 15 +++++ .../number_property_weak_error4.phpt | 15 +++++ .../number_property_weak_error5.phpt | 15 +++++ .../number_property_weak_error6.phpt | 24 +++++++ .../number_property_weak_error7.phpt | 24 +++++++ .../number_property_weak_success.phpt | 13 ++++ .../number_return_strict_error1.phpt | 13 ++++ .../number_return_strict_error2.phpt | 62 +++++++++++++++++++ .../number_return_strict_success.phpt | 16 +++++ .../validation/number_return_weak_error1.phpt | 18 ++++++ .../validation/number_return_weak_error2.phpt | 40 ++++++++++++ .../number_return_weak_success.phpt | 25 ++++++++ Zend/zend_API.c | 4 +- Zend/zend_ast.c | 2 + Zend/zend_compile.c | 32 +++++++--- Zend/zend_operators.c | 6 +- Zend/zend_string.h | 1 + Zend/zend_type_info.h | 2 + Zend/zend_types.h | 7 ++- ext/com_dotnet/com_handlers.c | 2 +- ext/gmp/gmp.c | 2 +- ext/simplexml/simplexml.c | 2 +- ext/tidy/tidy.c | 4 +- 58 files changed, 948 insertions(+), 20 deletions(-) create mode 100644 Zend/tests/type_declarations/number/casting/number_cast_error.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_error1.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success1.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success2.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success3.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success4.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error1.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error2.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error3.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error1.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error2.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success1.phpt create mode 100644 Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success2.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/nullable_number_parameter_success.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/nullable_number_property_success.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/nullable_number_return_success.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/number_parameter_error.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/number_parameter_success.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/number_return_error.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/number_return_success.phpt create mode 100644 Zend/tests/type_declarations/number/syntax/number_void_return_error.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_parameter_strict_error.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_parameter_strict_success.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_parameter_weak_error.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_parameter_weak_success.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error1.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error2.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error3.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error4.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error5.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error6.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_error7.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_strict_success.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error1.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error2.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error3.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error4.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error5.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error6.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_error7.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_property_weak_success.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_strict_error1.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_strict_error2.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_strict_success.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_weak_error1.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_weak_error2.phpt create mode 100644 Zend/tests/type_declarations/number/validation/number_return_weak_success.phpt diff --git a/Zend/tests/type_declarations/number/casting/number_cast_error.phpt b/Zend/tests/type_declarations/number/casting/number_cast_error.phpt new file mode 100644 index 0000000000000..f7b42bc40a35b --- /dev/null +++ b/Zend/tests/type_declarations/number/casting/number_cast_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Test that a number casting is not supported +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected '12' (T_LNUMBER) in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_error1.phpt b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_error1.phpt new file mode 100644 index 0000000000000..74fc324c516a0 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_error1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a number parameter type can't be narrowed +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of Bar::method(int $a) must be compatible with Foo::method(number $a) in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success1.phpt b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success1.phpt new file mode 100644 index 0000000000000..6f8521462ea48 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success1.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test that a number parameter type supports invariance +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success2.phpt b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success2.phpt new file mode 100644 index 0000000000000..4a90f638d7126 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success2.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test that a number parameter type supports invariance +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success3.phpt b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success3.phpt new file mode 100644 index 0000000000000..6c62a567a1997 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success3.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test that a narrower type can be overridden by the number type +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success4.phpt b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success4.phpt new file mode 100644 index 0000000000000..fa75392a229fa --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_parameter_inheritance_success4.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test that a parameter of a nullable int type can be overridden by the nullable number type +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error1.phpt b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error1.phpt new file mode 100644 index 0000000000000..937111ade5698 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a property of number type can't be overridden by a property of any other type +--FILE-- + +--EXPECTF-- +Fatal error: Type of Bar::$property1 must be number (as in class Foo) in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error2.phpt b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error2.phpt new file mode 100644 index 0000000000000..454c7571322cc --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error2.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a property of number type can't be overridden by a property of any other type type +--FILE-- + +--EXPECTF-- +Fatal error: Type of Bar::$property1 must be number (as in class Foo) in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error3.phpt b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error3.phpt new file mode 100644 index 0000000000000..c38a465e6f712 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_property_inheritance_error3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a property of number type can't be overridden by a property of any other type type +--FILE-- + +--EXPECTF-- +Fatal error: Type of Bar::$property1 must be number (as in class Foo) in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error1.phpt b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error1.phpt new file mode 100644 index 0000000000000..1011dcab22b6f --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a number return type can't be widened +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of Bar::method(): int|float|null must be compatible with Foo::method(): number in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error2.phpt b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error2.phpt new file mode 100644 index 0000000000000..02f58ec71bf3b --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_error2.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that a number return type can't be widened +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of Bar::method(): int|float|null must be compatible with Foo::method(): number in %s on line %d diff --git a/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success1.phpt b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success1.phpt new file mode 100644 index 0000000000000..e1e6a0bc4aa9e --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success1.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test that a number return value supports invariance +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success2.phpt b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success2.phpt new file mode 100644 index 0000000000000..cdbe306719328 --- /dev/null +++ b/Zend/tests/type_declarations/number/inheritance/number_return_inheritance_success2.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test that a number return type can be overridden by any subtype +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/syntax/nullable_number_parameter_success.phpt b/Zend/tests/type_declarations/number/syntax/nullable_number_parameter_success.phpt new file mode 100644 index 0000000000000..3d7d5ba398670 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/nullable_number_parameter_success.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test that the nullable number parameter type is valid +--FILE-- + +--EXPECTF-- diff --git a/Zend/tests/type_declarations/number/syntax/nullable_number_property_success.phpt b/Zend/tests/type_declarations/number/syntax/nullable_number_property_success.phpt new file mode 100644 index 0000000000000..0e196018472b1 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/nullable_number_property_success.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test that the nullable number property type is valid +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/syntax/nullable_number_return_success.phpt b/Zend/tests/type_declarations/number/syntax/nullable_number_return_success.phpt new file mode 100644 index 0000000000000..86b1497287874 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/nullable_number_return_success.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test that the nullable number return type is valid +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/syntax/number_parameter_error.phpt b/Zend/tests/type_declarations/number/syntax/number_parameter_error.phpt new file mode 100644 index 0000000000000..2bfd499a3a501 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/number_parameter_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test that the number parameter type can't be used together with any other numeric type +--FILE-- + +--EXPECTF-- +Fatal error: Duplicate type int is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/number/syntax/number_parameter_success.phpt b/Zend/tests/type_declarations/number/syntax/number_parameter_success.phpt new file mode 100644 index 0000000000000..49007a4ec02e3 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/number_parameter_success.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test that number is a valid parameter type +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/syntax/number_return_error.phpt b/Zend/tests/type_declarations/number/syntax/number_return_error.phpt new file mode 100644 index 0000000000000..f83fa622fca26 --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/number_return_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test that the number return type can't be used together with any other numeric type +--FILE-- + +--EXPECTF-- +Fatal error: Duplicate type float is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/number/syntax/number_return_success.phpt b/Zend/tests/type_declarations/number/syntax/number_return_success.phpt new file mode 100644 index 0000000000000..3975e2e47791e --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/number_return_success.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test that number is a valid return type +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/syntax/number_void_return_error.phpt b/Zend/tests/type_declarations/number/syntax/number_void_return_error.phpt new file mode 100644 index 0000000000000..0a597800b4f8c --- /dev/null +++ b/Zend/tests/type_declarations/number/syntax/number_void_return_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test that the number|void return type is not valid +--FILE-- + +--EXPECTF-- +Fatal error: Void can only be used as a standalone type in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_parameter_strict_error.phpt b/Zend/tests/type_declarations/number/validation/number_parameter_strict_error.phpt new file mode 100644 index 0000000000000..3d2c9560f455f --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_parameter_strict_error.phpt @@ -0,0 +1,47 @@ +--TEST-- +Test that the number parameter type doesn't accept non-numeric types in strict mode +--FILE-- +getMessage() . "\n"; +} + +try { + foo("0"); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo([]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(new stdClass()); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(fopen(__FILE__, "r")); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +?> +--EXPECTF-- +foo(): Argument #1 ($a) must be of type number, null given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, string given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, array given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, object given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, resource given, called in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_parameter_strict_success.phpt b/Zend/tests/type_declarations/number/validation/number_parameter_strict_success.phpt new file mode 100644 index 0000000000000..5a64fb228ea8d --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_parameter_strict_success.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that the number parameter type accepts integer and float arguments in strict mode +--FILE-- + +--EXPECT-- +int(1) +float(3.14) diff --git a/Zend/tests/type_declarations/number/validation/number_parameter_weak_error.phpt b/Zend/tests/type_declarations/number/validation/number_parameter_weak_error.phpt new file mode 100644 index 0000000000000..effede348bd30 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_parameter_weak_error.phpt @@ -0,0 +1,39 @@ +--TEST-- +Test that the number parameter type doesn't accept any kind of non-numeric value in weak mode +--FILE-- +getMessage() . "\n"; +} + +try { + foo([]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(new stdClass()); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(fopen(__FILE__, "r")); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +?> +--EXPECTF-- +foo(): Argument #1 ($a) must be of type number, string given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, array given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, object given, called in %s on line %d +foo(): Argument #1 ($a) must be of type number, resource given, called in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_parameter_weak_success.phpt b/Zend/tests/type_declarations/number/validation/number_parameter_weak_success.phpt new file mode 100644 index 0000000000000..8b5cc6228a995 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_parameter_weak_success.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test that the number parameter type accepts any kind of numeric argument in weak mode +--FILE-- + +--EXPECTF-- +int(0) +int(1) +int(1) +float(3.14) +int(0) + +Notice: A non well formed numeric value encountered in %s on line %d +int(12) diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error1.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error1.phpt new file mode 100644 index 0000000000000..bba45e651502b --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error1.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- + +--EXPECTF-- +Fatal error: Default value for property of type number may not be null. Use the nullable type ?number to allow null default value in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error2.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error2.phpt new file mode 100644 index 0000000000000..d4b09b11349c7 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error2.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use bool as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error3.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error3.phpt new file mode 100644 index 0000000000000..33ac257773c64 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error3.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use bool as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error4.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error4.phpt new file mode 100644 index 0000000000000..6cfc926cf0116 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error4.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use string as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error5.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error5.phpt new file mode 100644 index 0000000000000..adbb5d837051a --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error5.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use array as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error6.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error6.phpt new file mode 100644 index 0000000000000..d0be68b6247ab --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error6.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- +property1 = new stdClass(); + } +} + +$foo = new Foo(); + +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign stdClass to property Foo::$property1 of type number in %s:%d +Stack trace: +#0 %s(%d): Foo->__construct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_error7.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_error7.phpt new file mode 100644 index 0000000000000..c3e1dbbb2c7c8 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_error7.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric type in strict mode +--FILE-- +property1 = fopen(__FILE__, "r"); + } +} + +$foo = new Foo(); + +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign resource to property Foo::$property1 of type number in %s:%d +Stack trace: +#0 %s(%d): Foo->__construct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_strict_success.phpt b/Zend/tests/type_declarations/number/validation/number_property_strict_success.phpt new file mode 100644 index 0000000000000..fe5cb5a41e9ea --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_strict_success.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test that the number property type accepts integer and float types in strict mode +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error1.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error1.phpt new file mode 100644 index 0000000000000..bdab80c6eb5dc --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error1.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- + +--EXPECTF-- +Fatal error: Default value for property of type number may not be null. Use the nullable type ?number to allow null default value in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error2.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error2.phpt new file mode 100644 index 0000000000000..84aa0f877852a --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error2.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use bool as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error3.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error3.phpt new file mode 100644 index 0000000000000..319ccac7e03a7 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error3.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use bool as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error4.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error4.phpt new file mode 100644 index 0000000000000..10ada82380cf9 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error4.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use string as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error5.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error5.phpt new file mode 100644 index 0000000000000..045f10c7318ad --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error5.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use array as default value for property Foo::$property1 of type number in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error6.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error6.phpt new file mode 100644 index 0000000000000..0118a0d6ec531 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error6.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- +property1 = new stdClass(); + } +} + +$foo = new Foo(); + +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign stdClass to property Foo::$property1 of type number in %s:%d +Stack trace: +#0 %s(%d): Foo->__construct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_error7.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_error7.phpt new file mode 100644 index 0000000000000..4666412ec193c --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_error7.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test that the number property type doesn't accept any non-numeric value in weak mode +--FILE-- +property1 = fopen(__FILE__, "r"); + } +} + +$foo = new Foo(); + +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Cannot assign resource to property Foo::$property1 of type number in %s:%d +Stack trace: +#0 %s(%d): Foo->__construct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/type_declarations/number/validation/number_property_weak_success.phpt b/Zend/tests/type_declarations/number/validation/number_property_weak_success.phpt new file mode 100644 index 0000000000000..2885dd24e48bd --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_property_weak_success.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test that the number property type accepts any numeric value in weak mode +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/validation/number_return_strict_error1.phpt b/Zend/tests/type_declarations/number/validation/number_return_strict_error1.phpt new file mode 100644 index 0000000000000..83114061107d1 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_strict_error1.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test that the number return type is not compatible with a void return value in strict mode +--FILE-- + +--EXPECT-- + diff --git a/Zend/tests/type_declarations/number/validation/number_return_strict_error2.phpt b/Zend/tests/type_declarations/number/validation/number_return_strict_error2.phpt new file mode 100644 index 0000000000000..3e97af35311d4 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_strict_error2.phpt @@ -0,0 +1,62 @@ +--TEST-- +Test that the number return type is not compatible with a void return value in strict mode +--FILE-- +getMessage() . "\n"; +} + +try { + foo(false); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(true); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo("0"); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo([]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(new stdClass()); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(fopen(__FILE__, "r")); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +?> +--EXPECT-- +Return value of foo() must be of type number, null returned +Return value of foo() must be of type number, bool returned +Return value of foo() must be of type number, bool returned +Return value of foo() must be of type number, string returned +Return value of foo() must be of type number, array returned +Return value of foo() must be of type number, object returned +Return value of foo() must be of type number, resource returned diff --git a/Zend/tests/type_declarations/number/validation/number_return_strict_success.phpt b/Zend/tests/type_declarations/number/validation/number_return_strict_success.phpt new file mode 100644 index 0000000000000..83ad65b0765d3 --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_strict_success.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test that the number return type is compatible with any kind of numeric type in strict mode +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/type_declarations/number/validation/number_return_weak_error1.phpt b/Zend/tests/type_declarations/number/validation/number_return_weak_error1.phpt new file mode 100644 index 0000000000000..19372381eecea --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_weak_error1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test that the number return type is not compatible with a void return value +--FILE-- +getMessage() . "\n"; +} + +?> +--EXPECT-- +Return value of foo() must be of type number, none returned diff --git a/Zend/tests/type_declarations/number/validation/number_return_weak_error2.phpt b/Zend/tests/type_declarations/number/validation/number_return_weak_error2.phpt new file mode 100644 index 0000000000000..b1388298a789f --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_weak_error2.phpt @@ -0,0 +1,40 @@ +--TEST-- +Test that the number return type is not compatible with non-numeric return values +--FILE-- +getMessage() . "\n"; +} + +try { + foo([]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(new stdClass()); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + foo(fopen(__FILE__, "r")); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +?> +--EXPECT-- +Return value of foo() must be of type number, null returned +Return value of foo() must be of type number, array returned +Return value of foo() must be of type number, object returned +Return value of foo() must be of type number, resource returned diff --git a/Zend/tests/type_declarations/number/validation/number_return_weak_success.phpt b/Zend/tests/type_declarations/number/validation/number_return_weak_success.phpt new file mode 100644 index 0000000000000..f775052ef5add --- /dev/null +++ b/Zend/tests/type_declarations/number/validation/number_return_weak_success.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test that the number return type is compatible with any numeric value in weak mode +--FILE-- + +--EXPECTF-- +int(0) +int(1) +int(1) +float(3.14) + +Notice: A non well formed numeric value encountered in %s on line %d +int(0) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 4aa76ca111036..52c8753cd51ad 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -123,8 +123,10 @@ ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */ return "array"; case IS_VOID: return "void"; - case _IS_NUMBER: + case IS_NUMBER: return "number"; + case IS_SCALAR: + return "scalar"; default: return "unknown"; } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 7cfc0450fd84e..3ea21d2369469 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1572,6 +1572,8 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case IS_ARRAY: APPEND_STR("array"); case IS_CALLABLE: APPEND_STR("callable"); case IS_STATIC: APPEND_STR("static"); + case IS_NUMBER: APPEND_STR("number"); + case IS_SCALAR: APPEND_STR("scalar"); EMPTY_SWITCH_DEFAULT_CASE(); } break; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bb279d5570b8e..37d577bced8dd 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -172,6 +172,8 @@ static const struct reserved_class_name reserved_class_names[] = { {ZEND_STRL("void")}, {ZEND_STRL("iterable")}, {ZEND_STRL("object")}, + {ZEND_STRL("number")}, + {ZEND_STRL("scalar")}, {NULL, 0} }; @@ -220,6 +222,8 @@ static const builtin_type_info builtin_types[] = { {ZEND_STRL("void"), IS_VOID}, {ZEND_STRL("iterable"), IS_ITERABLE}, {ZEND_STRL("object"), IS_OBJECT}, + {ZEND_STRL("number"), IS_NUMBER}, + {ZEND_STRL("scalar"), IS_SCALAR}, {NULL, 0, IS_UNDEF} }; @@ -1166,6 +1170,7 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { zend_string *str = NULL; + if (ZEND_TYPE_HAS_LIST(type)) { zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { @@ -1204,15 +1209,25 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop if (type_mask & MAY_BE_ARRAY) { str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY)); } + + if (type_mask == MAY_BE_SCALAR) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_SCALAR)); + } else if (type_mask == MAY_BE_NUMBER) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NUMBER)); + } else { + if (type_mask & MAY_BE_LONG) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT)); + } + + if (type_mask & MAY_BE_DOUBLE) { + str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT)); + } + } + if (type_mask & MAY_BE_STRING) { str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING)); } - if (type_mask & MAY_BE_LONG) { - str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT)); - } - if (type_mask & MAY_BE_DOUBLE) { - str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT)); - } + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) { str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL)); } else if (type_mask & MAY_BE_FALSE) { @@ -5580,8 +5595,9 @@ static zend_type zend_compile_typename( for (uint32_t i = 0; i < list->children; i++) { zend_ast *type_ast = list->child[i]; zend_type single_type = zend_compile_single_typename(type_ast); - uint32_t type_mask_overlap = - ZEND_TYPE_PURE_MASK(type) & ZEND_TYPE_PURE_MASK(single_type); + uint32_t single_type_mask = ZEND_TYPE_PURE_MASK(single_type); + + uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask; if (type_mask_overlap) { zend_type overlap_type = ZEND_TYPE_INIT_MASK(type_mask_overlap); zend_string *overlap_type_str = zend_type_to_string(overlap_type); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 7f9b804f1e067..9ded426f7ae55 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -181,7 +181,7 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ { zval dst; - convert_object_to_type(op, &dst, _IS_NUMBER); + convert_object_to_type(op, &dst, IS_NUMBER); zval_ptr_dtor(op); if (Z_TYPE(dst) == IS_LONG || Z_TYPE(dst) == IS_DOUBLE) { @@ -215,7 +215,7 @@ static zend_never_inline zval* ZEND_FASTCALL _zendi_convert_scalar_to_number_sil ZVAL_LONG(holder, Z_RES_HANDLE_P(op)); return holder; case IS_OBJECT: - convert_object_to_type(op, holder, _IS_NUMBER); + convert_object_to_type(op, holder, IS_NUMBER); if (UNEXPECTED(EG(exception)) || UNEXPECTED(Z_TYPE_P(holder) != IS_LONG && Z_TYPE_P(holder) != IS_DOUBLE)) { ZVAL_LONG(holder, 1); @@ -252,7 +252,7 @@ static zend_never_inline int ZEND_FASTCALL _zendi_try_convert_scalar_to_number(z ZVAL_LONG(holder, Z_RES_HANDLE_P(op)); return SUCCESS; case IS_OBJECT: - convert_object_to_type(op, holder, _IS_NUMBER); + convert_object_to_type(op, holder, IS_NUMBER); if (UNEXPECTED(EG(exception))) { return FAILURE; } diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 45ef3cbb01b71..39959b0828b3c 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -522,6 +522,7 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_VOID, "void") \ _(ZEND_STR_FALSE, "false") \ _(ZEND_STR_NULL_LOWERCASE, "null") \ + _(ZEND_STR_NUMBER, "number") \ typedef enum _zend_known_string_id { diff --git a/Zend/zend_type_info.h b/Zend/zend_type_info.h index bace8014bfc3f..000462e968135 100644 --- a/Zend/zend_type_info.h +++ b/Zend/zend_type_info.h @@ -41,6 +41,8 @@ #define MAY_BE_ITERABLE (1 << IS_ITERABLE) #define MAY_BE_VOID (1 << IS_VOID) #define MAY_BE_STATIC (1 << IS_STATIC) +#define MAY_BE_NUMBER (MAY_BE_LONG|MAY_BE_DOUBLE) +#define MAY_BE_SCALAR (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING) #define MAY_BE_ARRAY_SHIFT (IS_REFERENCE) diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 3543277b779bf..02cfe5b9d7ae0 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -257,7 +257,7 @@ typedef struct { { NULL, (_type_mask) } #define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \ - ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? MAY_BE_BOOL : (1 << (code))) \ + ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? MAY_BE_BOOL : ((code) == IS_NUMBER ? MAY_BE_NUMBER : (1 << (code)))) \ | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags)) #define ZEND_TYPE_INIT_PTR(ptr, type_kind, allow_null, extra_flags) \ @@ -534,6 +534,8 @@ struct _zend_ast_ref { #define IS_ITERABLE 13 #define IS_VOID 14 #define IS_STATIC 15 +#define IS_NUMBER 16 +#define IS_SCALAR 17 /* internal types */ #define IS_INDIRECT 12 @@ -542,8 +544,7 @@ struct _zend_ast_ref { #define _IS_ERROR 15 /* used for casts */ -#define _IS_BOOL 16 -#define _IS_NUMBER 17 +#define _IS_BOOL 18 static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index cd1f59f555005..5be999123d500 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -451,7 +451,7 @@ static int com_object_cast(zend_object *readobj, zval *writeobj, int type) switch(type) { case IS_LONG: - case _IS_NUMBER: + case IS_NUMBER: vt = VT_INT; break; case IS_DOUBLE: diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index a14c65f2978df..e7a90275e4ec5 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -289,7 +289,7 @@ static int gmp_cast_object(zend_object *readobj, zval *writeobj, int type) /* {{ gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum)); return SUCCESS; - case _IS_NUMBER: + case IS_NUMBER: gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; if (mpz_fits_slong_p(gmpnum)) { ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 5f23c48026a41..13c3040073640 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1874,7 +1874,7 @@ static int cast_object(zval *object, int type, char *contents) case IS_DOUBLE: convert_to_double(object); break; - case _IS_NUMBER: + case IS_NUMBER: convert_scalar_to_number(object); break; default: diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index b9f9c3502a03b..8e517376c28f0 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -523,7 +523,7 @@ static int tidy_doc_cast_handler(zend_object *in, zval *out, int type) switch (type) { case IS_LONG: - case _IS_NUMBER: + case IS_NUMBER: ZVAL_LONG(out, 0); break; @@ -561,7 +561,7 @@ static int tidy_node_cast_handler(zend_object *in, zval *out, int type) switch(type) { case IS_LONG: - case _IS_NUMBER: + case IS_NUMBER: ZVAL_LONG(out, 0); break;