summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-09-23 16:12:18 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-09-23 16:20:26 +0200
commit5dcbc65a53b7f7c6e517b19260c637017528b3f9 (patch)
treeefe5dce103f86dfe9ba616466bc2d2403fecdfa6
parentb7745d6eeb39dffc616ef48b92b6b2cfc7e571a5 (diff)
downloadphp-git-5dcbc65a53b7f7c6e517b19260c637017528b3f9.tar.gz
Canonicalize typed prop/param default value errors
Use shared logic to determine what values are valid, and a single error message format.
-rw-r--r--Zend/tests/bug69767.phpt2
-rw-r--r--Zend/tests/errmsg_013.phpt2
-rw-r--r--Zend/tests/object_types/invalid_default_value.phpt2
-rw-r--r--Zend/tests/type_declarations/iterable_002.phpt2
-rw-r--r--Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt2
-rw-r--r--Zend/tests/type_declarations/typed_properties_013.phpt2
-rw-r--r--Zend/tests/type_declarations/typed_properties_014.phpt2
-rw-r--r--Zend/zend_compile.c101
-rw-r--r--tests/lang/type_hints_003.phpt2
9 files changed, 48 insertions, 69 deletions
diff --git a/Zend/tests/bug69767.phpt b/Zend/tests/bug69767.phpt
index 9458546dea..095bfd89d5 100644
--- a/Zend/tests/bug69767.phpt
+++ b/Zend/tests/bug69767.phpt
@@ -5,4 +5,4 @@ Bug #69767 (Default parameter value with wrong type segfaults)
function foo(String $bar = 0) {}
?>
--EXPECTF--
-Fatal error: Default value for parameters with a string type can only be string or NULL in %sbug69767.php on line %d
+Fatal error: Cannot use int as default value for parameter $bar of type string in %s on line %d
diff --git a/Zend/tests/errmsg_013.phpt b/Zend/tests/errmsg_013.phpt
index 606282458b..037ef9b1aa 100644
--- a/Zend/tests/errmsg_013.phpt
+++ b/Zend/tests/errmsg_013.phpt
@@ -11,4 +11,4 @@ class test {
echo "Done\n";
?>
--EXPECTF--
-Fatal error: Default value for parameters with array type can only be an array or NULL in %s on line %d
+Fatal error: Cannot use string as default value for parameter $a of type array in %s on line %d
diff --git a/Zend/tests/object_types/invalid_default_value.phpt b/Zend/tests/object_types/invalid_default_value.phpt
index 2768e00e7d..39272b05c0 100644
--- a/Zend/tests/object_types/invalid_default_value.phpt
+++ b/Zend/tests/object_types/invalid_default_value.phpt
@@ -7,4 +7,4 @@ function test(object $obj = 42) { }
?>
--EXPECTF--
-Fatal error: Default value for parameters with an object type can only be NULL in %s on line %d
+Fatal error: Cannot use int as default value for parameter $obj of type object in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable_002.phpt b/Zend/tests/type_declarations/iterable_002.phpt
index b9e02e40cd..fdc3b20df5 100644
--- a/Zend/tests/type_declarations/iterable_002.phpt
+++ b/Zend/tests/type_declarations/iterable_002.phpt
@@ -17,4 +17,4 @@ function baz(iterable $iterable = 1) {
?>
--EXPECTF--
-Fatal error: Default value for parameters with iterable type can only be an array or NULL in %s on line %d
+Fatal error: Cannot use int as default value for parameter $iterable of type iterable in %s on line %d
diff --git a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt
index fd7f96ab95..fc6fc21b17 100644
--- a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt
+++ b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt
@@ -12,4 +12,4 @@ test();
?>
--EXPECTF--
-Fatal error: Default value for parameters with a float type can only be float, integer, or NULL in %s on line %d
+Fatal error: Cannot use bool as default value for parameter $arg of type float in %s on line %d
diff --git a/Zend/tests/type_declarations/typed_properties_013.phpt b/Zend/tests/type_declarations/typed_properties_013.phpt
index 01c2f4b6a0..7236e21a2c 100644
--- a/Zend/tests/type_declarations/typed_properties_013.phpt
+++ b/Zend/tests/type_declarations/typed_properties_013.phpt
@@ -7,4 +7,4 @@ class Foo {
}
?>
--EXPECTF--
-Fatal error: Default value for property of type int can only be int in %s on line 3
+Fatal error: Cannot use string as default value for property Foo::$bar of type int in %s on line 3
diff --git a/Zend/tests/type_declarations/typed_properties_014.phpt b/Zend/tests/type_declarations/typed_properties_014.phpt
index 2a02f0381e..f7a4449abd 100644
--- a/Zend/tests/type_declarations/typed_properties_014.phpt
+++ b/Zend/tests/type_declarations/typed_properties_014.phpt
@@ -7,4 +7,4 @@ class Foo {
}
?>
--EXPECTF--
-Fatal error: Default value for property of type array can only be an array in %s on line 3
+Fatal error: Cannot use int as default value for property Foo::$bar of type array in %s on line 3
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 373792548f..1e20ff95b9 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5343,6 +5343,29 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
}
/* }}} */
+static zend_bool zend_is_valid_default_value(zend_type type, zval *value)
+{
+ ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
+ if (Z_TYPE_P(value) == IS_NULL && ZEND_TYPE_ALLOW_NULL(type)) {
+ return 1;
+ }
+
+ if (ZEND_TYPE_IS_CLASS(type)) {
+ return 0;
+ }
+ if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
+ return 1;
+ }
+ if ((ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
+ /* Integers are allowed as initializers for floating-point values. */
+ return 1;
+ }
+ if ((ZEND_TYPE_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) {
+ return 1;
+ }
+ return 0;
+}
+
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
@@ -5449,41 +5472,13 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
}
- if (default_type > IS_NULL && default_type != IS_CONSTANT_AST) {
- if (is_class) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with a class type can only be NULL");
- } else {
- if (arg_type & MAY_BE_CALLABLE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with callable type can only be NULL");
- } else if (arg_type & MAY_BE_ARRAY) {
- if (default_type != IS_ARRAY) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with array type can only be an array or NULL");
- }
- } else if (arg_type & MAY_BE_DOUBLE) {
- if (default_type != IS_DOUBLE && default_type != IS_LONG) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with a float type can only be float, integer, or NULL");
- }
- } else if (arg_type & MAY_BE_ITERABLE) {
- if (default_type != IS_ARRAY) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with iterable type can only be an array or NULL");
- }
- } else if (arg_type & MAY_BE_OBJECT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with an object type can only be NULL");
- } else if (!ZEND_TYPE_CONTAINS_CODE(arg_type, default_type)) {
- zend_string *type_str =
- zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(arg_type));
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with a %s type can only be %s or NULL",
- ZSTR_VAL(type_str), ZSTR_VAL(type_str));
- zend_string_release(type_str);
- }
- }
+ if (default_type > IS_NULL && default_type != IS_CONSTANT_AST
+ && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) {
+ zend_string *type_str = zend_type_to_string(arg_info->type);
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use %s as default value for parameter $%s of type %s",
+ zend_get_type_by_const(default_type),
+ ZSTR_VAL(name), ZSTR_VAL(type_str));
}
/* Allocate cache slot to speed-up run-time class resolution */
@@ -6034,35 +6029,19 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /
if (value_ast) {
zend_const_expr_to_zval(&value_zv, value_ast);
- if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) {
+ if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)
+ && !zend_is_valid_default_value(type, &value_zv)) {
+ zend_string *str = zend_type_to_string(type);
if (Z_TYPE(value_zv) == IS_NULL) {
- if (!ZEND_TYPE_ALLOW_NULL(type)) {
- zend_string *str = zend_type_to_string(type);
- zend_error_noreturn(E_COMPILE_ERROR,
- "Default value for property of type %s may not be null. "
- "Use the nullable type ?%s to allow null default value",
- ZSTR_VAL(str), ZSTR_VAL(str));
- }
- } else if (ZEND_TYPE_IS_CLASS(type)) {
zend_error_noreturn(E_COMPILE_ERROR,
- "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type)));
- } else if (ZEND_TYPE_MASK(type) & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
- if (Z_TYPE(value_zv) != IS_ARRAY) {
- zend_string *str = zend_type_to_string(type);
- zend_error_noreturn(E_COMPILE_ERROR,
- "Default value for property of type %s can only be an array",
- ZSTR_VAL(str));
- }
- } else if (ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) {
- if (Z_TYPE(value_zv) != IS_DOUBLE && Z_TYPE(value_zv) != IS_LONG) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Default value for property of type float can only be float or int");
- }
- } else if (!ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(value_zv))) {
- zend_string *str = zend_type_to_string(type);
+ "Default value for property of type %s may not be null. "
+ "Use the nullable type ?%s to allow null default value",
+ ZSTR_VAL(str), ZSTR_VAL(str));
+ } else {
zend_error_noreturn(E_COMPILE_ERROR,
- "Default value for property of type %s can only be %s",
- ZSTR_VAL(str), ZSTR_VAL(str));
+ "Cannot use %s as default value for property %s::$%s of type %s",
+ zend_get_type_by_const(Z_TYPE(value_zv)),
+ ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str));
}
}
} else if (!ZEND_TYPE_IS_SET(type)) {
diff --git a/tests/lang/type_hints_003.phpt b/tests/lang/type_hints_003.phpt
index f6b04dabff..00471b9448 100644
--- a/tests/lang/type_hints_003.phpt
+++ b/tests/lang/type_hints_003.phpt
@@ -8,4 +8,4 @@ class T {
}
?>
--EXPECTF--
-Fatal error: Default value for parameters with a class type can only be NULL in %stype_hints_003.php on line 3
+Fatal error: Cannot use int as default value for parameter $p of type P in %s on line %d