Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Zend/tests/typehints/mixed.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
Test various types passed to mixed type.
--FILE--
<?php

$types = [
NULL,
TRUE,
123,
123.456,
'php',
new stdClass,
fopen(__FILE__, 'r'),
];

function test(mixed $arg) {
var_dump($arg);
}

foreach ($types as $type) {
test($type);
}
--EXPECTF--
NULL
bool(true)
int(123)
float(123.456)
string(3) "php"
object(stdClass)#%d (%d) {
}
resource(%d) of type (stream)
27 changes: 27 additions & 0 deletions Zend/tests/typehints/mixed_inheritance.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
Test mixed variance in inheritance.
--FILE--
<?php

class Foo {
function test(mixed $arg): mixed
{
return $arg;
}
}

class Bar extends Foo {
function test($arg) {
return parent::test($arg);
}
}

class Baz extends bar {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: bar in lower case

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bar

function test(mixed $arg): mixed {
return parent::test($arg);
}
}

var_dump((new Baz())->test(123));
--EXPECT--
int(123)
10 changes: 10 additions & 0 deletions Zend/tests/typehints/mixed_nullable_parameter.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
Test nullable mixed parameter type.
--FILE--
<?php

function test(?mixed $arg) {
}

--EXPECTF--
Fatal error: Mixed type cannot be nullable in %smixed_nullable_parameter.php on line %d
10 changes: 10 additions & 0 deletions Zend/tests/typehints/mixed_nullable_return.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
Test nullable mixed return type.
--FILE--
<?php

function test($arg): ?mixed {
}

--EXPECTF--
Fatal error: Mixed type cannot be nullable in %smixed_nullable_return.php on line %d
2 changes: 2 additions & 0 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
10 changes: 10 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}
};

Expand Down Expand Up @@ -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}
};

Expand Down Expand Up @@ -5486,6 +5488,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
}

if (ZEND_TYPE_CODE(arg_infos->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 {
Expand Down Expand Up @@ -5581,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
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
8 changes: 7 additions & 1 deletion Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this can be simplified:

Suggested change
return 0;
return ZEND_TYPE_CODE(fe_arg_info->type) == IS_MIXED;

}

Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this can be simplified:

Suggested change
return 0;
return ZEND_TYPE_CODE(proto->common.arg_info[-1].type) == IS_MIXED;

}

Expand Down
1 change: 1 addition & 0 deletions Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down