From 120b7f0b504f40582d5e78df7cd0f17781eeece2 Mon Sep 17 00:00:00 2001 From: Michael Moravec Date: Fri, 29 Jun 2018 13:30:52 +0200 Subject: [PATCH 1/2] Added mixed argument type & return type Co-Authored-By: Gabriel Caruso --- Zend/tests/typehints/mixed.phpt | 31 +++++++++++++++++++++ Zend/tests/typehints/mixed_inheritance.phpt | 27 ++++++++++++++++++ Zend/zend_API.c | 2 ++ Zend/zend_compile.c | 2 ++ Zend/zend_execute.c | 2 ++ Zend/zend_inheritance.c | 8 +++++- Zend/zend_types.h | 1 + 7 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/typehints/mixed.phpt create mode 100644 Zend/tests/typehints/mixed_inheritance.phpt diff --git a/Zend/tests/typehints/mixed.phpt b/Zend/tests/typehints/mixed.phpt new file mode 100644 index 0000000000000..dac5f91b65ed0 --- /dev/null +++ b/Zend/tests/typehints/mixed.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test various types passed to mixed type. +--FILE-- +test(123)); +--EXPECT-- +int(123) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b05c5a96d4757..912d6eb47cdb2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -128,6 +128,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */ return "void"; case _IS_NUMBER: return "number"; + case IS_MIXED: + return "mixed"; default: return "unknown"; } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 310fac9cc973e..7d943be8844db 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -176,6 +176,7 @@ static const struct reserved_class_name reserved_class_names[] = { {ZEND_STRL("void")}, {ZEND_STRL("iterable")}, {ZEND_STRL("object")}, + {ZEND_STRL("mixed")}, {NULL, 0} }; @@ -222,6 +223,7 @@ static const builtin_type_info builtin_types[] = { {ZEND_STRL("void"), IS_VOID}, {ZEND_STRL("iterable"), IS_ITERABLE}, {ZEND_STRL("object"), IS_OBJECT}, + {ZEND_STRL("mixed"), IS_MIXED}, {NULL, 0, IS_UNDEF} }; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 55c24f31e98b4..60004fba5b79d 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -945,6 +945,8 @@ static zend_always_inline zend_bool zend_check_type( } else if (ZEND_TYPE_CODE(type) == _IS_BOOL && EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) { return 1; + } else if (ZEND_TYPE_CODE(type) == IS_MIXED) { + return 1; } else { return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg, is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES()); diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index be605a49de6c2..cc7f3c8c2c0ec 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -253,7 +253,10 @@ static int zend_do_perform_arg_type_hint_check(const zend_function *fe, zend_arg } if (!ZEND_TYPE_IS_SET(proto_arg_info->type)) { - /* Child defines a type, but parent doesn't, violates LSP */ + /* Child defines a type, but parent doesn't, violates LSP, unless it's a mixed type */ + if (ZEND_TYPE_CODE(fe_arg_info->type) == IS_MIXED) { + return 1; + } return 0; } @@ -359,6 +362,9 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c if (proto->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { /* Removing a return type is not valid. */ if (!(fe->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { + if (ZEND_TYPE_CODE(proto->common.arg_info[-1].type) == IS_MIXED) { + return 1; + } return 0; } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 59b0af1a4a818..2cb8eadc19569 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -407,6 +407,7 @@ struct _zend_ast_ref { #define IS_ITERABLE 18 #define IS_VOID 19 #define _IS_NUMBER 20 +#define IS_MIXED 21 static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; From eec8dd9d237edaeafc698cd5ad1153f8e082696b Mon Sep 17 00:00:00 2001 From: Michael Moravec Date: Fri, 29 Jun 2018 13:30:56 +0200 Subject: [PATCH 2/2] Disallow nullable mixed types at compile time Co-Authored-By: Gabriel Caruso --- Zend/tests/typehints/mixed_nullable_parameter.phpt | 10 ++++++++++ Zend/tests/typehints/mixed_nullable_return.phpt | 10 ++++++++++ Zend/zend_compile.c | 8 ++++++++ 3 files changed, 28 insertions(+) create mode 100644 Zend/tests/typehints/mixed_nullable_parameter.phpt create mode 100644 Zend/tests/typehints/mixed_nullable_return.phpt diff --git a/Zend/tests/typehints/mixed_nullable_parameter.phpt b/Zend/tests/typehints/mixed_nullable_parameter.phpt new file mode 100644 index 0000000000000..922f394fb53e0 --- /dev/null +++ b/Zend/tests/typehints/mixed_nullable_parameter.phpt @@ -0,0 +1,10 @@ +--TEST-- +Test nullable mixed parameter type. +--FILE-- +type) == IS_MIXED && ZEND_TYPE_ALLOW_NULL(arg_infos->type)) { + zend_error_noreturn(E_COMPILE_ERROR, "Mixed type cannot be nullable"); + } + arg_infos++; op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; } else { @@ -5583,6 +5587,10 @@ 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 (ZEND_TYPE_CODE(arg_info->type) == IS_MIXED && ZEND_TYPE_ALLOW_NULL(arg_info->type)) { + zend_error_noreturn(E_COMPILE_ERROR, "Mixed type cannot be nullable"); + } + if (type_ast->kind == ZEND_AST_TYPE) { if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { if (default_ast && !has_null_default