Skip to content

[RFC] Union types #1887

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
make error messages better
  • Loading branch information
krakjoe committed Apr 25, 2016
commit 5f9436865d7d8afc3574f15240d04e12ab141def
2 changes: 1 addition & 1 deletion Zend/tests/multi/008.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ class Bar extends Foo {
}
?>
--EXPECTF--
Warning: Declaration of Bar::method($arg) should be compatible with Foo::method(Traversable or array $arg) in %s on line 8
Warning: Declaration of Bar::method($arg) should be compatible with Foo::method(Traversable | array $arg) in %s on line 8
2 changes: 1 addition & 1 deletion Zend/tests/multi/009.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ class Bar extends Foo {
}
?>
--EXPECTF--
Warning: Declaration of Bar::method($arg) should be compatible with Foo::method(IFoo and IBar $arg) in %s on line 8
Warning: Declaration of Bar::method($arg) should be compatible with Foo::method(IFoo & IBar $arg) in %s on line 8
2 changes: 1 addition & 1 deletion Zend/tests/multi/010.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ class Bar extends Foo {
}
?>
--EXPECTF--
Fatal error: Declaration of Bar::method() must be compatible with Foo::method(): IFoo and IBar in %s on line 8
Fatal error: Declaration of Bar::method() must be compatible with Foo::method(): IFoo & IBar in %s on line 8
2 changes: 1 addition & 1 deletion Zend/tests/multi/scalar_008.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ int(1)
float(1.1)
bool(true)

Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be true or integer or float, string given, called in %s on line %d and defined in %s:%d
Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be true, integer or float, string given, called in %s on line %d and defined in %s:%d
Stack trace:
#0 %s(%d): foo('')
#1 {main}
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/multi/scalar_009.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Notice: A non well formed numeric value encountered in %s on line %d
float(1.1)
bool(false)

Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be false or integer or float, string given, called in %s on line %d and defined in %s:%d
Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be false, integer or float, string given, called in %s on line %d and defined in %s:%d
Stack trace:
#0 %s(%d): foo('invalid')
#1 {main}
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4952,13 +4952,13 @@ static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{
arg_info->multi.types = non_callable;
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot require parameters to be %s at the same time in intersection types",
ZSTR_VAL(zend_get_multi_type_declaration(&arg_info->multi)));
ZSTR_VAL(zend_get_multi_type_declaration(&arg_info->multi, 1)));
}
if (arg_info->multi.types & ~(MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_CALLABLE|MAY_BE_OBJECT)) {
arg_info->multi.types &= ~(MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_CALLABLE|MAY_BE_OBJECT);
zend_error_noreturn(E_COMPILE_ERROR,
"Scalar types %s are disallowed in intersection types",
ZSTR_VAL(zend_get_multi_type_declaration(&arg_info->multi)));
ZSTR_VAL(zend_get_multi_type_declaration(&arg_info->multi, 1)));
}
}

Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a

if (UNEXPECTED(cur_arg_info->multi.types)) {
if (UNEXPECTED(!zend_verify_multi_type(&cur_arg_info->multi, cur_arg_info->allow_null, arg, cache_slot, ZEND_ARG_USES_STRICT_TYPES()))) {
zend_string *decl = zend_get_multi_type_declaration(&cur_arg_info->multi);
zend_string *decl = zend_get_multi_type_declaration(&cur_arg_info->multi, 1);
zend_verify_arg_error(zf, arg_num, "be ", ZSTR_VAL(decl),
Z_TYPE_P(arg) == IS_OBJECT ?
"instance of " : "",
Expand Down Expand Up @@ -1240,7 +1240,7 @@ static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *
if (ret_info->type_hint) {
if (UNEXPECTED(ret_info->multi.types)) {
if (UNEXPECTED(!zend_verify_multi_type(&ret_info->multi, ret_info->allow_null, ret, cache_slot, ZEND_RET_USES_STRICT_TYPES()))) {
zend_string *decl = zend_get_multi_type_declaration(&ret_info->multi);
zend_string *decl = zend_get_multi_type_declaration(&ret_info->multi, 1);
zend_verify_return_error(zf, "be ", ZSTR_VAL(decl),
Z_TYPE_P(ret) == IS_OBJECT ?
"instance of " : "",
Expand Down
52 changes: 48 additions & 4 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,61 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
}
/* }}} */

zend_string* zend_get_multi_type_declaration(zend_multi_type *m) { /* {{{ */
uint32_t zend_get_multi_type_count(zend_multi_type *m) {
uint32_t count = 0;

if (m->types & MAY_BE_TRUE)
count++;
if (m->types & MAY_BE_FALSE)
count++;
if (m->types & MAY_BE_BOOL)
count++;
if (m->types & MAY_BE_LONG)
count++;
if (m->types & MAY_BE_DOUBLE)
count++;
if (m->types & MAY_BE_CALLABLE)
count++;
if (m->types & MAY_BE_ARRAY)
count++;
if (m->types & MAY_BE_RESOURCE)
count++;

return count + m->last;
}

zend_string* zend_get_multi_type_declaration(zend_multi_type *m, zend_bool humans) { /* {{{ */
smart_str sm;
uint32_t types = m->types;
uint32_t types = m->types, count = zend_get_multi_type_count(m);

memset(&sm, 0, sizeof(smart_str));

smart_str_alloc(&sm, 42, 0);

#define APPEND_MULTI_TYPE_SEP() do { \
if (types) { \
smart_str_appends(&sm, m->type == ZEND_MULTI_UNION ? " or " : " and "); \
count--; \
if (m->type == ZEND_MULTI_UNION) { \
if (humans) { \
if (count > 1) { \
smart_str_appends(&sm, ", "); \
} else { \
smart_str_appends(&sm, " or "); \
} \
} else { \
smart_str_appends(&sm, " | "); \
} \
} else { \
if (humans) { \
if (count > 1) { \
smart_str_appends(&sm, ", "); \
} else { \
smart_str_appends(&sm, " and "); \
} \
} else { \
smart_str_appends(&sm, " & "); \
} \
} \
} \
} while(0)
#define APPEND_MULTI_TYPE(t, c) do { \
Expand Down Expand Up @@ -433,7 +477,7 @@ static ZEND_COLD void zend_append_type_hint(smart_str *str, const zend_function
{
if (arg_info->multi.types) {
zend_string *decl =
zend_get_multi_type_declaration(&arg_info->multi);
zend_get_multi_type_declaration(&arg_info->multi, 0);
smart_str_append(str, decl);
if (!return_hint) {
smart_str_appends(str, " ");
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_inheritance.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void zend_do_early_binding(void);

void zend_check_deprecated_constructor(const zend_class_entry *ce);

zend_string* zend_get_multi_type_declaration(zend_multi_type *u);
zend_string* zend_get_multi_type_declaration(zend_multi_type *u, zend_bool humans);

END_EXTERN_C()

Expand Down