diff options
author | Nicolas Grekas <nicolas.grekas@gmail.com> | 2020-01-13 17:06:26 +0100 |
---|---|---|
committer | Nicolas Grekas <nicolas.grekas@gmail.com> | 2020-03-02 15:25:32 +0100 |
commit | 9e775db02567d3b90694ebb43f0225875a48e8c9 (patch) | |
tree | cd25ebdb5e735ca322eded189b156619a4b43534 /Zend | |
parent | c06850b9fa1b6dc8f4f8a46d6d0ea55e8baf7cbf (diff) | |
download | php-git-9e775db02567d3b90694ebb43f0225875a48e8c9.tar.gz |
Define Stringable with __toString():string method
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/bug26166.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/list_keyed_evaluation_order.inc | 2 | ||||
-rw-r--r-- | Zend/tests/list_keyed_evaluation_order.phpt | 4 | ||||
-rw-r--r-- | Zend/tests/list_keyed_evaluation_order_nested.phpt | 10 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_basic.phpt | 12 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_return_basic.phpt | 12 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_return_basic_64bit.phpt | 12 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_strict.phpt | 12 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_strict_64bit.phpt | 12 | ||||
-rw-r--r-- | Zend/zend_compile.c | 19 | ||||
-rw-r--r-- | Zend/zend_exceptions.c | 2 | ||||
-rw-r--r-- | Zend/zend_exceptions.stub.php | 8 | ||||
-rw-r--r-- | Zend/zend_exceptions_arginfo.h | 5 | ||||
-rw-r--r-- | Zend/zend_interfaces.c | 10 | ||||
-rw-r--r-- | Zend/zend_interfaces.h | 1 | ||||
-rw-r--r-- | Zend/zend_interfaces.stub.php | 5 | ||||
-rw-r--r-- | Zend/zend_interfaces_arginfo.h | 3 |
17 files changed, 75 insertions, 56 deletions
diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt index 7e5668e47f..4a5a30f5b2 100644 --- a/Zend/tests/bug26166.phpt +++ b/Zend/tests/bug26166.phpt @@ -64,6 +64,6 @@ try { --EXPECT-- Hello World! ===NONE=== -Method NoneTest::__toString() must return a string value +Return value of NoneTest::__toString() must be of type string, none returned ===THROW=== This is an error! diff --git a/Zend/tests/list_keyed_evaluation_order.inc b/Zend/tests/list_keyed_evaluation_order.inc index d4ee778b63..577a19a838 100644 --- a/Zend/tests/list_keyed_evaluation_order.inc +++ b/Zend/tests/list_keyed_evaluation_order.inc @@ -2,7 +2,7 @@ // Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests -class Stringable +class StringCapable { private $name; public function __construct(string $name) { diff --git a/Zend/tests/list_keyed_evaluation_order.phpt b/Zend/tests/list_keyed_evaluation_order.phpt index 0f0652b6a9..3c5fb7e877 100644 --- a/Zend/tests/list_keyed_evaluation_order.phpt +++ b/Zend/tests/list_keyed_evaluation_order.phpt @@ -5,8 +5,8 @@ list() with keys, evaluation order require_once "list_keyed_evaluation_order.inc"; -$a = new Stringable("A"); -$c = new Stringable("C"); +$a = new StringCapable("A"); +$c = new StringCapable("C"); $e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"])); diff --git a/Zend/tests/list_keyed_evaluation_order_nested.phpt b/Zend/tests/list_keyed_evaluation_order_nested.phpt index 8a7725d4ea..496deefbb9 100644 --- a/Zend/tests/list_keyed_evaluation_order_nested.phpt +++ b/Zend/tests/list_keyed_evaluation_order_nested.phpt @@ -5,11 +5,11 @@ list() with keys, evaluation order: nested require_once "list_keyed_evaluation_order.inc"; -$a = new Stringable("A"); -$c = new Stringable("C"); -$f = new Stringable("F"); -$g = new Stringable("G"); -$i = new Stringable("I"); +$a = new StringCapable("A"); +$c = new StringCapable("C"); +$f = new StringCapable("F"); +$g = new StringCapable("G"); +$i = new StringCapable("I"); $k = new IndexableRetrievable("K", new Indexable([ "A" => "offset value for A", diff --git a/Zend/tests/type_declarations/scalar_basic.phpt b/Zend/tests/type_declarations/scalar_basic.phpt index e4b8ab5c51..c3f06c5bbd 100644 --- a/Zend/tests/type_declarations/scalar_basic.phpt +++ b/Zend/tests/type_declarations/scalar_basic.phpt @@ -19,7 +19,7 @@ $functions = [ 'bool' => function (bool $b) { return $b; } ]; -class Stringable { +class StringCapable implements Stringable { public function __toString() { return "foobar"; } @@ -40,7 +40,7 @@ $values = [ NULL, [], new StdClass, - new Stringable, + new StringCapable, fopen("data:text/plain,foobar", "r") ]; @@ -106,7 +106,7 @@ int(0) } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d -*** Trying object(Stringable)#%s (0) { +*** Trying object(StringCapable)#%s (0) { } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d @@ -160,7 +160,7 @@ float(0) } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d -*** Trying object(Stringable)#%s (0) { +*** Trying object(StringCapable)#%s (0) { } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d @@ -213,7 +213,7 @@ string(0) "" } *** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d -*** Trying object(Stringable)#%s (0) { +*** Trying object(StringCapable)#%s (0) { } string(6) "foobar" @@ -266,7 +266,7 @@ bool(false) } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d -*** Trying object(Stringable)#%s (0) { +*** Trying object(StringCapable)#%s (0) { } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d diff --git a/Zend/tests/type_declarations/scalar_return_basic.phpt b/Zend/tests/type_declarations/scalar_return_basic.phpt index 9ee50f8457..c0b0df6829 100644 --- a/Zend/tests/type_declarations/scalar_return_basic.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic.phpt @@ -21,7 +21,7 @@ $functions = [ 'bool' => function ($b): bool { return $b; } ]; -class Stringable { +class StringCapable { public function __toString() { return "foobar"; } @@ -42,7 +42,7 @@ $values = [ NULL, [], new StdClass, - new Stringable, + new StringCapable, fopen("data:text/plain,foobar", "r") ]; @@ -94,7 +94,7 @@ int(0) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type int, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type int, object returned in %s on line %d *** Trying resource(5) of type (stream) @@ -132,7 +132,7 @@ float(0) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type float, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type float, object returned in %s on line %d *** Trying resource(5) of type (stream) @@ -169,7 +169,7 @@ string(0) "" *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type string, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } string(6) "foobar" *** Trying resource(5) of type (stream) @@ -206,7 +206,7 @@ bool(false) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d *** Trying resource(5) of type (stream) diff --git a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt index ad987e58da..5e387c45c8 100644 --- a/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt +++ b/Zend/tests/type_declarations/scalar_return_basic_64bit.phpt @@ -21,7 +21,7 @@ $functions = [ 'bool' => function ($b): bool { return $b; } ]; -class Stringable { +class StringCapable { public function __toString() { return "foobar"; } @@ -42,7 +42,7 @@ $values = [ NULL, [], new StdClass, - new Stringable, + new StringCapable, fopen("data:text/plain,foobar", "r") ]; @@ -94,7 +94,7 @@ int(0) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type int, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type int, object returned in %s on line %d *** Trying resource(5) of type (stream) @@ -132,7 +132,7 @@ float(0) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type float, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type float, object returned in %s on line %d *** Trying resource(5) of type (stream) @@ -169,7 +169,7 @@ string(0) "" *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type string, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } string(6) "foobar" *** Trying resource(5) of type (stream) @@ -206,7 +206,7 @@ bool(false) *** Trying object(stdClass)#6 (0) { } *** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d -*** Trying object(Stringable)#7 (0) { +*** Trying object(StringCapable)#7 (0) { } *** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d *** Trying resource(5) of type (stream) diff --git a/Zend/tests/type_declarations/scalar_strict.phpt b/Zend/tests/type_declarations/scalar_strict.phpt index 032fd3d301..3c420ed455 100644 --- a/Zend/tests/type_declarations/scalar_strict.phpt +++ b/Zend/tests/type_declarations/scalar_strict.phpt @@ -13,7 +13,7 @@ $functions = [ 'bool' => function (bool $b) { return $b; } ]; -class Stringable { +class StringCapable { public function __toString() { return "foobar"; } @@ -34,7 +34,7 @@ $values = [ NULL, [], new StdClass, - new Stringable, + new StringCapable, fopen("data:text/plain,foobar", "r") ]; @@ -100,7 +100,7 @@ int(2147483647) } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d @@ -153,7 +153,7 @@ float(NAN) } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d @@ -206,7 +206,7 @@ string(0) "" } *** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d @@ -259,7 +259,7 @@ bool(false) } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d diff --git a/Zend/tests/type_declarations/scalar_strict_64bit.phpt b/Zend/tests/type_declarations/scalar_strict_64bit.phpt index 5818606b4c..6f8504c16c 100644 --- a/Zend/tests/type_declarations/scalar_strict_64bit.phpt +++ b/Zend/tests/type_declarations/scalar_strict_64bit.phpt @@ -13,7 +13,7 @@ $functions = [ 'bool' => function (bool $b) { return $b; } ]; -class Stringable { +class StringCapable { public function __toString() { return "foobar"; } @@ -34,7 +34,7 @@ $values = [ NULL, [], new StdClass, - new Stringable, + new StringCapable, fopen("data:text/plain,foobar", "r") ]; @@ -100,7 +100,7 @@ int(9223372036854775807) } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d @@ -153,7 +153,7 @@ float(NAN) } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d @@ -206,7 +206,7 @@ string(0) "" } *** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d @@ -259,7 +259,7 @@ bool(false) } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d -*** Trying object(Stringable)#6 (0) { +*** Trying object(StringCapable)#6 (0) { } *** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f7ba3acf9d..cbf5ebfc02 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5714,7 +5714,7 @@ static zend_bool zend_is_valid_default_value(zend_type type, zval *value) return 0; } -void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ +void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fallback_return_type) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; @@ -5722,14 +5722,18 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_arg_info *arg_infos; zend_string *optional_param = NULL; - if (return_type_ast) { + if (return_type_ast || fallback_return_type) { /* Use op_array->arg_info[-1] for return type */ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0); arg_infos->name = NULL; - arg_infos->type = zend_compile_typename( - return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0); - ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS( - (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0); + if (return_type_ast) { + arg_infos->type = zend_compile_typename( + return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0); + ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS( + (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0); + } else { + arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0); + } arg_infos++; op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; } else { @@ -6294,7 +6298,8 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var); } - zend_compile_params(params_ast, return_type_ast); + zend_compile_params(params_ast, return_type_ast, + is_method && zend_string_equals_literal_ci(decl->name, "__toString") ? IS_STRING : 0); if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) { zend_mark_function_as_generator(); zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index f3846d326b..fb48d34bdf 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -763,7 +763,6 @@ static const zend_function_entry zend_funcs_throwable[] = { ZEND_ABSTRACT_ME(throwable, getTrace, arginfo_class_Throwable_getTrace) ZEND_ABSTRACT_ME(throwable, getPrevious, arginfo_class_Throwable_getPrevious) ZEND_ABSTRACT_ME(throwable, getTraceAsString, arginfo_class_Throwable_getTraceAsString) - ZEND_ABSTRACT_ME(throwable, __toString, arginfo_class_Throwable___toString) ZEND_FE_END }; /* }}} */ @@ -805,6 +804,7 @@ void zend_register_default_exception(void) /* {{{ */ zend_class_entry ce; REGISTER_MAGIC_INTERFACE(throwable, Throwable); + zend_class_implements(zend_ce_throwable, 1, zend_ce_stringable); memcpy(&default_exception_handlers, &std_object_handlers, sizeof(zend_object_handlers)); default_exception_handlers.clone_obj = NULL; diff --git a/Zend/zend_exceptions.stub.php b/Zend/zend_exceptions.stub.php index 96d581caf9..12255df3f6 100644 --- a/Zend/zend_exceptions.stub.php +++ b/Zend/zend_exceptions.stub.php @@ -1,6 +1,6 @@ <?php -interface Throwable +interface Throwable extends Stringable { /** @return string */ function getMessage(); @@ -22,9 +22,6 @@ interface Throwable /** @return string */ function getTraceAsString(); - - /** @return string */ - function __toString(); } class Exception implements Throwable @@ -56,8 +53,7 @@ class Exception implements Throwable /** @return string */ final function getTraceAsString() {} - /** @return string */ - function __toString() {} + function __toString(): string {} } class ErrorException extends Exception diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index c2f83e47e5..93badb6652 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -15,8 +15,6 @@ ZEND_END_ARG_INFO() #define arginfo_class_Throwable_getTraceAsString arginfo_class_Throwable_getMessage -#define arginfo_class_Throwable___toString arginfo_class_Throwable_getMessage - #define arginfo_class_Exception___clone arginfo_class_Throwable_getMessage ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Exception___construct, 0, 0, 0) @@ -41,7 +39,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_Exception_getTraceAsString arginfo_class_Throwable_getMessage -#define arginfo_class_Exception___toString arginfo_class_Throwable_getMessage +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Exception___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ErrorException___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index b6fdec95be..db42202571 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -28,6 +28,7 @@ ZEND_API zend_class_entry *zend_ce_iterator; ZEND_API zend_class_entry *zend_ce_arrayaccess; ZEND_API zend_class_entry *zend_ce_serializable; ZEND_API zend_class_entry *zend_ce_countable; +ZEND_API zend_class_entry *zend_ce_stringable; /* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ @@ -567,6 +568,11 @@ static const zend_function_entry zend_funcs_countable[] = { ZEND_ABSTRACT_ME(Countable, count, arginfo_class_Countable_count) ZEND_FE_END }; + +static const zend_function_entry zend_funcs_stringable[] = { + ZEND_ABSTRACT_ME(Stringable, __toString, arginfo_class_Stringable___toString) + ZEND_FE_END +}; /* }}} */ /* {{{ zend_register_interfaces */ @@ -585,5 +591,9 @@ ZEND_API void zend_register_interfaces(void) REGISTER_MAGIC_INTERFACE(serializable, Serializable); REGISTER_MAGIC_INTERFACE(countable, Countable); + + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, "Stringable", zend_funcs_stringable); + zend_ce_stringable = zend_register_internal_interface(&ce); } /* }}} */ diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index e7d0315ac5..c79495eca3 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -30,6 +30,7 @@ extern ZEND_API zend_class_entry *zend_ce_iterator; extern ZEND_API zend_class_entry *zend_ce_arrayaccess; extern ZEND_API zend_class_entry *zend_ce_serializable; extern ZEND_API zend_class_entry *zend_ce_countable; +extern ZEND_API zend_class_entry *zend_ce_stringable; typedef struct _zend_user_iterator { zend_object_iterator it; diff --git a/Zend/zend_interfaces.stub.php b/Zend/zend_interfaces.stub.php index 882a21e600..3a908212a4 100644 --- a/Zend/zend_interfaces.stub.php +++ b/Zend/zend_interfaces.stub.php @@ -49,3 +49,8 @@ interface Countable /** @return int */ function count(); } + +interface Stringable +{ + function __toString(): string; +} diff --git a/Zend/zend_interfaces_arginfo.h b/Zend/zend_interfaces_arginfo.h index fee57057af..e96104719a 100644 --- a/Zend/zend_interfaces_arginfo.h +++ b/Zend/zend_interfaces_arginfo.h @@ -33,3 +33,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Serializable_unserialize, 0, 0, 1) ZEND_END_ARG_INFO() #define arginfo_class_Countable_count arginfo_class_IteratorAggregate_getIterator + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Stringable___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() |