From 9e775db02567d3b90694ebb43f0225875a48e8c9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Mon, 13 Jan 2020 17:06:26 +0100 Subject: [PATCH 1/2] Define Stringable with __toString():string method --- Zend/tests/bug26166.phpt | 2 +- Zend/tests/list_keyed_evaluation_order.inc | 2 +- Zend/tests/list_keyed_evaluation_order.phpt | 4 +- .../list_keyed_evaluation_order_nested.phpt | 10 +- .../tests/type_declarations/scalar_basic.phpt | 12 +- .../scalar_return_basic.phpt | 12 +- .../scalar_return_basic_64bit.phpt | 12 +- .../type_declarations/scalar_strict.phpt | 12 +- .../scalar_strict_64bit.phpt | 12 +- Zend/zend_compile.c | 19 +- Zend/zend_exceptions.c | 2 +- Zend/zend_exceptions.stub.php | 8 +- Zend/zend_exceptions_arginfo.h | 5 +- Zend/zend_interfaces.c | 10 + Zend/zend_interfaces.h | 1 + Zend/zend_interfaces.stub.php | 5 + Zend/zend_interfaces_arginfo.h | 3 + ext/reflection/php_reflection.c | 3 +- ext/reflection/php_reflection.stub.php | 33 +- ext/reflection/php_reflection_arginfo.h | 309 +++++++++--------- .../tests/ReflectionClass_toString_001.phpt | 5 +- ext/simplexml/simplexml.c | 2 +- ext/simplexml/simplexml.stub.php | 5 +- ext/simplexml/simplexml_arginfo.h | 3 +- ext/soap/soap.stub.php | 3 +- ext/soap/soap_arginfo.h | 19 +- ext/spl/spl_directory.c | 10 +- ext/spl/spl_iterators.c | 6 +- ext/spl/spl_iterators.h | 1 + ext/standard/tests/strings/strlen.phpt | Bin 6096 -> 6102 bytes ext/standard/tests/strings/strpos.phpt | Bin 8035 -> 8041 bytes ext/standard/tests/strings/strstr.phpt | Bin 9512 -> 9518 bytes ext/standard/tests/strings/ucfirst.phpt | Bin 4684 -> 4690 bytes sapi/cli/tests/005.phpt | 5 +- tests/classes/tostring_001.phpt | 4 +- tests/classes/tostring_004.phpt | 6 +- 36 files changed, 282 insertions(+), 263 deletions(-) diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt index 7e5668e47ff4c..4a5a30f5b298f 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 d4ee778b634ac..577a19a83803a 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 0f0652b6a9b43..3c5fb7e8770c1 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 8a7725d4eaaae..496deefbb9879 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 e4b8ab5c51e0b..c3f06c5bbde87 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 9ee50f8457700..c0b0df6829678 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 ad987e58da596..5e387c45c8f26 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 032fd3d3015be..3c420ed4551ba 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 5818606b4cfda..6f8504c16c639 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 f7ba3acf9d0e0..cbf5ebfc02445 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 f3846d326bbae..fb48d34bdf61b 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 96d581caf97e4..12255df3f6eeb 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 @@ function getPrevious(); /** @return string */ function getTraceAsString(); - - /** @return string */ - function __toString(); } class Exception implements Throwable @@ -56,8 +53,7 @@ final function getPrevious() {} /** @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 c2f83e47e50b2..93badb6652896 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 b6fdec95bea4b..db422025718f0 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 e7d0315ac5d00..c79495eca3f55 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 882a21e60048e..3a908212a4631 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 fee57057afa0c..e96104719aeed 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() diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 793cf5de2fe47..05a016b97cff7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6214,7 +6214,6 @@ static const zend_function_entry reflection_functions[] = { }; static const zend_function_entry reflector_functions[] = { - ZEND_ABSTRACT_ME(reflector, __toString, arginfo_class_Reflector___toString) PHP_FE_END }; @@ -6522,6 +6521,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */ INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions); reflector_ptr = zend_register_internal_interface(&_reflection_entry); + zend_class_implements(reflector_ptr, 1, zend_ce_stringable); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions); reflection_init_class_handlers(&_reflection_entry); @@ -6550,6 +6550,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */ reflection_init_class_handlers(&_reflection_entry); reflection_type_ptr = zend_register_internal_class(&_reflection_entry); reflection_type_ptr->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; + zend_class_implements(reflection_type_ptr, 1, zend_ce_stringable); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions); reflection_init_class_handlers(&_reflection_entry); diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index dc6b7014737e1..05e1b0490de5e 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -10,10 +10,8 @@ class Reflection public static function getModifierNames(int $modifiers) {} } -interface Reflector +interface Reflector extends Stringable { - /** @return string */ - public function __toString(); } abstract class ReflectionFunctionAbstract implements Reflector @@ -101,8 +99,7 @@ class ReflectionFunction extends ReflectionFunctionAbstract /** @param string|Closure $name */ public function __construct($name) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return bool */ public function isDisabled() {} @@ -143,8 +140,7 @@ class ReflectionMethod extends ReflectionFunctionAbstract /** @param object|string $class_or_method */ public function __construct($class_or_method, string $name = UNKNOWN) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return bool */ public function isPublic() {} @@ -197,8 +193,7 @@ final private function __clone() {} /** @param object|string $argument */ public function __construct($argument) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string|false */ public function getName() {} @@ -367,8 +362,7 @@ final private function __clone() {} /** @param string|object $class */ public function __construct($class, string $name) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string|false */ public function getName() {} @@ -427,8 +421,7 @@ final private function __clone() {} /** @return string|object */ public function __construct($class, string $name) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string|false */ public function getName() {} @@ -464,8 +457,7 @@ final private function __clone() {} */ public function __construct($function, $parameter) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string|false */ public function getName() {} @@ -521,15 +513,14 @@ public function getDefaultValueConstantName() {} public function isVariadic() {} } -abstract class ReflectionType +abstract class ReflectionType implements Stringable { final private function __clone() {} /** @return bool */ public function allowsNull() {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} } class ReflectionNamedType extends ReflectionType @@ -552,8 +543,7 @@ final private function __clone() {} public function __construct(string $name) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string|false */ public function getName() {} @@ -595,8 +585,7 @@ final private function __clone() {} public function __construct(string $name) {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return string */ public function getName() {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 5f5079f59edf2..45ead8eaac9b5 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -4,68 +4,67 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Reflector___toString, 0, 0, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunctionAbstract___clone, 0, 0, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFunctionAbstract___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_inNamespace arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_inNamespace arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isClosure arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isClosure arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isDeprecated arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isDeprecated arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isInternal arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isInternal arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isUserDefined arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isUserDefined arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isGenerator arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isGenerator arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_isVariadic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_isVariadic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getClosureThis arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getClosureThis arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getDocComment arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getDocComment arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getEndLine arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getEndLine arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getExtension arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getExtension arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getExtensionName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getExtensionName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getFileName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getFileName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getNamespaceName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getNamespaceName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getNumberOfParameters arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getNumberOfParameters arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getNumberOfRequiredParameters arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getNumberOfRequiredParameters arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getParameters arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getParameters arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getShortName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getShortName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getStartLine arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getStartLine arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getStaticVariables arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_getStaticVariables arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_returnsReference arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_returnsReference arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_hasReturnType arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionFunctionAbstract_hasReturnType arginfo_class_Reflector___toString - -#define arginfo_class_ReflectionFunctionAbstract_getReturnType arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunctionAbstract_getReturnType arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunction___construct, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFunction___toString arginfo_class_Reflector___toString +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunction___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFunction_isDisabled arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunction_isDisabled arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunction_invoke, 0, 0, 0) ZEND_ARG_VARIADIC_INFO(0, args) @@ -75,54 +74,54 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionFunction_invokeArgs, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFunction_getClosure arginfo_class_Reflector___toString +#define arginfo_class_ReflectionFunction_getClosure arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionGenerator___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, generator, Generator, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionGenerator_getExecutingLine arginfo_class_Reflector___toString +#define arginfo_class_ReflectionGenerator_getExecutingLine arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionGenerator_getExecutingFile arginfo_class_Reflector___toString +#define arginfo_class_ReflectionGenerator_getExecutingFile arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionGenerator_getTrace, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, options, IS_LONG, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionGenerator_getFunction arginfo_class_Reflector___toString +#define arginfo_class_ReflectionGenerator_getFunction arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionGenerator_getThis arginfo_class_Reflector___toString +#define arginfo_class_ReflectionGenerator_getThis arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionGenerator_getExecutingGenerator arginfo_class_Reflector___toString +#define arginfo_class_ReflectionGenerator_getExecutingGenerator arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionMethod___construct, 0, 0, 1) ZEND_ARG_INFO(0, class_or_method) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionMethod___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionMethod_isPublic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isPublic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isPrivate arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isPrivate arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isProtected arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isProtected arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isAbstract arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isAbstract arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isFinal arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isFinal arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isStatic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isStatic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isConstructor arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isConstructor arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_isDestructor arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_isDestructor arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionMethod_getClosure, 0, 0, 0) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionMethod_getModifiers arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_getModifiers arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionMethod_invoke, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 1) @@ -134,43 +133,43 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionMethod_invokeArgs, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionMethod_getDeclaringClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_getDeclaringClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionMethod_getPrototype arginfo_class_Reflector___toString +#define arginfo_class_ReflectionMethod_getPrototype arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionMethod_setAccessible, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, visible, _IS_BOOL, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass___clone arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass___construct, 0, 0, 1) ZEND_ARG_INFO(0, argument) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionClass_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isInternal arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isInternal arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isUserDefined arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isUserDefined arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isAnonymous arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isAnonymous arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isInstantiable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isInstantiable arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isCloneable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isCloneable arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getFileName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getFileName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getStartLine arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getStartLine arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getEndLine arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getEndLine arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getDocComment arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getDocComment arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getConstructor arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getConstructor arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_hasMethod, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -190,33 +189,33 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionClass_hasConstant arginfo_class_ReflectionClass_hasMethod -#define arginfo_class_ReflectionClass_getConstants arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getConstants arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getReflectionConstants arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getReflectionConstants arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionClass_getConstant arginfo_class_ReflectionClass_hasMethod #define arginfo_class_ReflectionClass_getReflectionConstant arginfo_class_ReflectionClass_hasMethod -#define arginfo_class_ReflectionClass_getInterfaces arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getInterfaces arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getInterfaceNames arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getInterfaceNames arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isInterface arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isInterface arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getTraits arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getTraits arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getTraitNames arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getTraitNames arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getTraitAliases arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getTraitAliases arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isTrait arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isTrait arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isAbstract arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isAbstract arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isFinal arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isFinal arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getModifiers arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getModifiers arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_isIntance, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) @@ -224,19 +223,19 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionClass_newInstance arginfo_class_ReflectionFunction_invoke -#define arginfo_class_ReflectionClass_newInstanceWithoutConstructor arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_newInstanceWithoutConstructor arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_newInstanceArgs, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass_getParentClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getParentClass arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_isSubclassOf, 0, 0, 1) ZEND_ARG_INFO(0, class) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass_getStaticProperties arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getStaticProperties arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_getStaticPropertyValue, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -248,40 +247,40 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_setStaticPropertyValue, 0, ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass_getDefaultProperties arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getDefaultProperties arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isIterable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isIterable arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_isIterateable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_isIterateable arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_implementsInterface, 0, 0, 1) ZEND_ARG_INFO(0, interface) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionClass_getExtension arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getExtension arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getExtensionName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getExtensionName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_inNamespace arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_inNamespace arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getNamespaceName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getNamespaceName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClass_getShortName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClass_getShortName arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionObject___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, argument, IS_OBJECT, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionProperty___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty___clone arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty___construct, 0, 0, 2) ZEND_ARG_INFO(0, class) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionProperty___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionProperty_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getName arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionProperty_getValue, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 1) @@ -294,156 +293,156 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionProperty_isInitialized arginfo_class_ReflectionProperty_getValue -#define arginfo_class_ReflectionProperty_isPublic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_isPublic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_isPrivate arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_isPrivate arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_isProtected arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_isProtected arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_isStatic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_isStatic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_isDefault arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_getDeclaringClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getDeclaringClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_getDocComment arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getDocComment arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionProperty_setAccessible arginfo_class_ReflectionMethod_setAccessible -#define arginfo_class_ReflectionProperty_getType arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getType arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionProperty_hasType arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_hasType arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_hasDefaultValue, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionProperty_getDefaultValue arginfo_class_Reflector___toString +#define arginfo_class_ReflectionProperty_getDefaultValue arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant___clone arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionClassConstant___construct arginfo_class_ReflectionProperty___construct -#define arginfo_class_ReflectionClassConstant___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionClassConstant_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_getValue arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_getValue arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_isPublic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_isPublic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_isPrivate arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_isPrivate arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_isProtected arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_isProtected arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_getModifiers arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_getModifiers arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_getDeclaringClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_getDeclaringClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionClassConstant_getDocComment arginfo_class_Reflector___toString +#define arginfo_class_ReflectionClassConstant_getDocComment arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter___clone arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionParameter___construct, 0, 0, 2) ZEND_ARG_INFO(0, function) ZEND_ARG_INFO(0, parameter) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionParameter___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionParameter_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isPassedByReference arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isPassedByReference arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_canBePassedByValue arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_canBePassedByValue arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getDeclaringFunction arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getDeclaringFunction arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getDeclaringClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getDeclaringClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getClass arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getClass arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_hasType arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_hasType arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getType arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getType arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isArray arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isArray arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isCallable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isCallable arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_allowsNull arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_allowsNull arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getPosition arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getPosition arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isOptional arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isOptional arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isDefaultValueAvailable arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isDefaultValueAvailable arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getDefaultValue arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getDefaultValue arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isDefaultValueConstant arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isDefaultValueConstant arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_getDefaultValueConstantName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_getDefaultValueConstantName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_Reflector___toString +#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionType___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionType___clone arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionType_allowsNull arginfo_class_Reflector___toString +#define arginfo_class_ReflectionType_allowsNull arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionType___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionType___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionNamedType_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionNamedType_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionNamedType_isBuiltin arginfo_class_Reflector___toString +#define arginfo_class_ReflectionNamedType_isBuiltin arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionUnionType_getTypes, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionExtension___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension___clone arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionExtension___construct arginfo_class_ReflectionClass_hasMethod -#define arginfo_class_ReflectionExtension___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionExtension_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getVersion arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getVersion arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getFunctions arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getFunctions arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getConstants arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getConstants arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getINIEntries arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getINIEntries arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getClasses arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getClasses arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getClassNames arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getClassNames arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_getDependencies arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_getDependencies arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_info arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_info arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_isPersistent arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_isPersistent arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionExtension_isTemporary arginfo_class_Reflector___toString +#define arginfo_class_ReflectionExtension_isTemporary arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionZendExtension___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension___clone arginfo_class_ReflectionFunctionAbstract___clone #define arginfo_class_ReflectionZendExtension___construct arginfo_class_ReflectionClass_hasMethod -#define arginfo_class_ReflectionZendExtension___toString arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension___toString arginfo_class_ReflectionFunction___toString -#define arginfo_class_ReflectionZendExtension_getName arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension_getName arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionZendExtension_getVersion arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension_getVersion arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionZendExtension_getAuthor arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension_getAuthor arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionZendExtension_getURL arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension_getURL arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionZendExtension_getCopyright arginfo_class_Reflector___toString +#define arginfo_class_ReflectionZendExtension_getCopyright arginfo_class_ReflectionFunctionAbstract___clone ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionReference_fromArrayElement, 0, 2, ReflectionReference, 1) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) @@ -453,6 +452,6 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionReference_getId, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionReference___clone arginfo_class_Reflector___toString +#define arginfo_class_ReflectionReference___clone arginfo_class_ReflectionFunctionAbstract___clone -#define arginfo_class_ReflectionReference___construct arginfo_class_Reflector___toString +#define arginfo_class_ReflectionReference___construct arginfo_class_ReflectionFunctionAbstract___clone diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt index 0aa46652b7b70..4eb82b96f3723 100644 --- a/ext/reflection/tests/ReflectionClass_toString_001.phpt +++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt @@ -9,7 +9,7 @@ $rc = new ReflectionClass("ReflectionClass"); echo $rc; ?> --EXPECT-- -Class [ <internal:Reflection> class ReflectionClass implements Reflector ] { +Class [ <internal:Reflection> class ReflectionClass implements Reflector, Stringable ] { - Constants [3] { Constant [ public int IS_IMPLICIT_ABSTRACT ] { 16 } @@ -41,10 +41,11 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] { } } - Method [ <internal:Reflection, prototype Reflector> public method __toString ] { + Method [ <internal:Reflection, prototype Stringable> public method __toString ] { - Parameters [0] { } + - Return [ string ] } Method [ <internal:Reflection> public method getName ] { diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 4e922e3ef0fbb..7a1a410c8ef23 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2633,7 +2633,7 @@ PHP_MINIT_FUNCTION(simplexml) sxe.create_object = sxe_object_new; sxe_class_entry = zend_register_internal_class(&sxe); sxe_class_entry->get_iterator = php_sxe_get_iterator; - zend_class_implements(sxe_class_entry, 2, zend_ce_traversable, zend_ce_countable); + zend_class_implements(sxe_class_entry, 3, zend_ce_traversable, zend_ce_countable, zend_ce_stringable); memcpy(&sxe_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); sxe_object_handlers.offset = XtOffsetOf(php_sxe_object, zo); diff --git a/ext/simplexml/simplexml.stub.php b/ext/simplexml/simplexml.stub.php index 3a1d0d51f4e3e..f78694c1399e8 100644 --- a/ext/simplexml/simplexml.stub.php +++ b/ext/simplexml/simplexml.stub.php @@ -6,7 +6,7 @@ function simplexml_load_string(string $data, ?string $class_name = SimpleXMLElem function simplexml_import_dom(DOMNode $node, ?string $class_name = SimpleXMLElement::class): ?SimpleXMLElement {} -class SimpleXMLElement +class SimpleXMLElement implements Stringable { /** @return array|false */ public function xpath(string $path) {} @@ -43,8 +43,7 @@ public function addAttribute(string $name, ?string $value = null, ?string $ns = /** @return string */ public function getName() {} - /** @return string */ - public function __toString() {} + public function __toString(): string {} /** @return int */ public function count() {} diff --git a/ext/simplexml/simplexml_arginfo.h b/ext/simplexml/simplexml_arginfo.h index b44426beebf57..06b9941b2e65f 100644 --- a/ext/simplexml/simplexml_arginfo.h +++ b/ext/simplexml/simplexml_arginfo.h @@ -71,6 +71,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_getName, 0, 0, 0) ZEND_END_ARG_INFO() -#define arginfo_class_SimpleXMLElement___toString arginfo_class_SimpleXMLElement_getName +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() #define arginfo_class_SimpleXMLElement_count arginfo_class_SimpleXMLElement_getName diff --git a/ext/soap/soap.stub.php b/ext/soap/soap.stub.php index 15ea54f660b22..77070dccf75cb 100644 --- a/ext/soap/soap.stub.php +++ b/ext/soap/soap.stub.php @@ -18,8 +18,7 @@ class SoapFault extends Exception { function __construct($faultcode, string $faultstring, ?string $faultactor = null, $detail = null, ?string $faultname = null, $headerfault = null); - /** @return string */ - function __toString(); + function __toString(): string; } class SoapVar diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index 69079b82eb5ac..82f30e9e67f6d 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -30,7 +30,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapFault___construct, 0, 0, 2) ZEND_ARG_INFO(0, headerfault) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapFault___toString, 0, 0, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SoapFault___toString, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapVar___construct, 0, 0, 2) @@ -72,7 +72,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapServer_setObject, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) ZEND_END_ARG_INFO() -#define arginfo_class_SoapServer_getFunctions arginfo_class_SoapFault___toString +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapServer_getFunctions, 0, 0, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapServer_addFunction, 0, 0, 1) ZEND_ARG_INFO(0, functions) @@ -97,17 +98,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapClient___soapCall, 0, 0, 2) ZEND_ARG_INFO(0, output_headers) ZEND_END_ARG_INFO() -#define arginfo_class_SoapClient___getFunctions arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getFunctions arginfo_class_SoapServer_getFunctions -#define arginfo_class_SoapClient___getTypes arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getTypes arginfo_class_SoapServer_getFunctions -#define arginfo_class_SoapClient___getLastRequest arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getLastRequest arginfo_class_SoapServer_getFunctions -#define arginfo_class_SoapClient___getLastResponse arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getLastResponse arginfo_class_SoapServer_getFunctions -#define arginfo_class_SoapClient___getLastRequestHeaders arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getLastRequestHeaders arginfo_class_SoapServer_getFunctions -#define arginfo_class_SoapClient___getLastResponseHeaders arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getLastResponseHeaders arginfo_class_SoapServer_getFunctions ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapClient___doRequest, 0, 0, 4) ZEND_ARG_TYPE_INFO(0, request, IS_STRING, 0) @@ -122,7 +123,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapClient___setCookie, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 1) ZEND_END_ARG_INFO() -#define arginfo_class_SoapClient___getCookies arginfo_class_SoapFault___toString +#define arginfo_class_SoapClient___getCookies arginfo_class_SoapServer_getFunctions ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SoapClient___setSoapHeaders, 0, 0, 0) ZEND_ARG_INFO(0, soapheaders) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index eb2b320792558..4ebbdf9cf771d 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1899,6 +1899,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_splfileinfo_void, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_splfileinfo___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + /* the method table */ /* each method can have its own parameters and visibility */ static const zend_function_entry spl_SplFileInfo_functions[] = { @@ -1933,7 +1936,7 @@ static const zend_function_entry spl_SplFileInfo_functions[] = { SPL_ME(SplFileInfo, setFileClass, arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC) SPL_ME(SplFileInfo, setInfoClass, arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC) SPL_ME(SplFileInfo, _bad_state_ex, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) - SPL_MA(SplFileInfo, __toString, SplFileInfo, getPathname, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) + SPL_MA(SplFileInfo, __toString, SplFileInfo, getPathname, arginfo_splfileinfo___toString, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -1959,7 +1962,7 @@ static const zend_function_entry spl_DirectoryIterator_functions[] = { SPL_ME(DirectoryIterator, current, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, next, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, seek, arginfo_dir_it_seek, ZEND_ACC_PUBLIC) - SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) + SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, arginfo_splfileinfo___toString, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -3072,7 +3075,7 @@ static const zend_function_entry spl_SplFileObject_functions[] = { SPL_ME(SplFileObject, seek, arginfo_file_object_seek, ZEND_ACC_PUBLIC) /* mappings */ SPL_MA(SplFileObject, getCurrentLine, SplFileObject, fgets, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) - SPL_MA(SplFileObject, __toString, SplFileObject, fgets, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) + SPL_MA(SplFileObject, __toString, SplFileObject, fgets, arginfo_splfileinfo___toString, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -3100,6 +3103,7 @@ PHP_MINIT_FUNCTION(spl_directory) spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage; spl_ce_SplFileInfo->serialize = zend_class_serialize_deny; spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny; + REGISTER_SPL_IMPLEMENTS(SplFileInfo, Stringable); REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions); diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 666f3ebf6485a..8aa35081e1b64 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -61,6 +61,9 @@ PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator; ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_void, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_caching_it___toString, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry spl_funcs_RecursiveIterator[] = { SPL_ABSTRACT_ME(RecursiveIterator, hasChildren, arginfo_recursive_it_void) SPL_ABSTRACT_ME(RecursiveIterator, getChildren, arginfo_recursive_it_void) @@ -2942,7 +2945,7 @@ static const zend_function_entry spl_funcs_CachingIterator[] = { SPL_ME(dual_it, current, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, next, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, hasNext, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) - SPL_ME(CachingIterator, __toString, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) + SPL_ME(CachingIterator, __toString, arginfo_caching_it___toString, ZEND_ACC_PUBLIC) SPL_ME(dual_it, getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, getFlags, arginfo_recursive_it_void, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, setFlags, arginfo_caching_it_setFlags, ZEND_ACC_PUBLIC) @@ -3662,6 +3665,7 @@ PHP_MINIT_FUNCTION(spl_iterators) REGISTER_SPL_SUB_CLASS_EX(CachingIterator, IteratorIterator, spl_dual_it_new, spl_funcs_CachingIterator); REGISTER_SPL_IMPLEMENTS(CachingIterator, ArrayAccess); REGISTER_SPL_IMPLEMENTS(CachingIterator, Countable); + REGISTER_SPL_IMPLEMENTS(CachingIterator, Stringable); REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING); REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD); diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h index a3b02bf8bce91..5d890bb2b90ab 100644 --- a/ext/spl/spl_iterators.h +++ b/ext/spl/spl_iterators.h @@ -27,6 +27,7 @@ #define spl_ce_ArrayAccess zend_ce_arrayaccess #define spl_ce_Serializable zend_ce_serializable #define spl_ce_Countable zend_ce_countable +#define spl_ce_Stringable zend_ce_stringable extern PHPAPI zend_class_entry *spl_ce_RecursiveIterator; extern PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator; diff --git a/ext/standard/tests/strings/strlen.phpt b/ext/standard/tests/strings/strlen.phpt index 6be163d8fe12a7452bd712eeacb622a51be14fa3..282db2da2d0bb29e5a481ee26162ca02f5cd8134 100644 GIT binary patch delta 36 jcmcbhe@%bG9(K;)lA_GKbmzo^$%oiO5WLMY99#GS5&sS9 delta 30 gcmcbne?fo49(K0klA_GK^vOrrL!ivfN*r7G0ms4&1poj5 diff --git a/ext/standard/tests/strings/strpos.phpt b/ext/standard/tests/strings/strpos.phpt index 59162e18222a294f56eef199ddb1a13344cf73c2..76175363466a5c319b7c098c6657871430101551 100644 GIT binary patch delta 36 jcmaEC_tI{IB^PIKNl|8Ax^rT|WP7d<1aI?9u2Uia1kw%2 delta 36 ocmaE9_t<WOB^O6=Nl|8AdScS#4P4rj^SRX7AOf4`bDa_a01dGYAOHXW diff --git a/ext/standard/tests/strings/strstr.phpt b/ext/standard/tests/strings/strstr.phpt index 4fa6165d971a82f5708ca79b055fc35075caa256..796a3476e9e7a88987d94266011d4969d42e3d0c 100644 GIT binary patch delta 36 jcmZ4Cwa#n9cQ(%8lA_GKbmzo^$$!~G5WLOd>=$JL8i)?5 delta 29 fcmZ4IwZdz|cQ&@-lA_GK^hxX?P}b&H_KUIrxfBb; diff --git a/ext/standard/tests/strings/ucfirst.phpt b/ext/standard/tests/strings/ucfirst.phpt index e7c0373a3cbda0e1d853ce741133e50b95e747cf..48fd772a04042b98d85a8fc8d409cce5bab795a3 100644 GIT binary patch delta 36 jcmX@3a!F-F0UKv<Nl|8Ax^rT|<TADp1aI>Nwi<2#0hSG@ delta 30 gcmcblaz<rC0UKL!Nl|8A`s7Ns5GZr=HMSaV0J_2p!vFvP diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt index d268104606350..ad0ea37c295d4 100644 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@ -37,7 +37,7 @@ string(183) "Class [ <internal:Core> class stdClass ] { } " -string(1969) "Class [ <internal:Core> class Exception implements Throwable ] { +string(2008) "Class [ <internal:Core> class Exception implements Throwable, Stringable ] { - Constants [0] { } @@ -122,10 +122,11 @@ string(1969) "Class [ <internal:Core> class Exception implements Throwable ] { } } - Method [ <internal:Core, prototype Throwable> public method __toString ] { + Method [ <internal:Core, prototype Stringable> public method __toString ] { - Parameters [0] { } + - Return [ string ] } } } diff --git a/tests/classes/tostring_001.phpt b/tests/classes/tostring_001.phpt index 3053da9140909..62791bf84e6b7 100644 --- a/tests/classes/tostring_001.phpt +++ b/tests/classes/tostring_001.phpt @@ -21,7 +21,7 @@ class test3 function __toString() { echo __METHOD__ . "()\n"; - return 42; + return []; } } echo "====test1====\n"; @@ -131,5 +131,5 @@ Converted object(test3)#2 (0) { } test3::__toString() -Method test3::__toString() must return a string value +Return value of test3::__toString() must be of type string, array returned ====DONE==== diff --git a/tests/classes/tostring_004.phpt b/tests/classes/tostring_004.phpt index 987298baa5fea..e07a7b21217eb 100644 --- a/tests/classes/tostring_004.phpt +++ b/tests/classes/tostring_004.phpt @@ -29,7 +29,7 @@ try { echo "\n\nObject with bad __toString():\n"; class badToString { function __toString() { - return 0; + return []; } } @@ -62,8 +62,8 @@ Object of class stdClass could not be converted to string Object with bad __toString(): Try 1: -Method badToString::__toString() must return a string value +Return value of badToString::__toString() must be of type string, array returned Try 2: -Method badToString::__toString() must return a string value +Return value of badToString::__toString() must be of type string, array returned From 336eb48c36f3c1c115349307c18e6cf16ab003df Mon Sep 17 00:00:00 2001 From: Nikita Popov <nikita.ppv@gmail.com> Date: Thu, 6 Feb 2020 10:27:30 +0100 Subject: [PATCH 2/2] Automatically implement Stringable interface --- UPGRADING | 2 ++ .../stringable_automatic_implementation.phpt | 35 +++++++++++++++++++ .../variance/stringable.phpt | 17 +++++++++ Zend/zend_compile.c | 27 +++++++++++--- .../tests/class_implements_variation1.phpt | 4 ++- 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 Zend/tests/stringable_automatic_implementation.phpt create mode 100644 Zend/tests/type_declarations/variance/stringable.phpt diff --git a/UPGRADING b/UPGRADING index 07d7f86f7c4a9..fcfb715622339 100644 --- a/UPGRADING +++ b/UPGRADING @@ -410,6 +410,8 @@ PHP 8.0 UPGRADE NOTES . Some consistency fixes to variable syntax have been applied, for example writing `Foo::BAR::$baz` is now allowed. RFC: https://wiki.php.net/rfc/variable_syntax_tweaks + . Added Stringable. + RFC: https://wiki.php.net/rfc/stringable - Date: . Added DateTime::createFromInterface() and diff --git a/Zend/tests/stringable_automatic_implementation.phpt b/Zend/tests/stringable_automatic_implementation.phpt new file mode 100644 index 0000000000000..5c45c03acbfa3 --- /dev/null +++ b/Zend/tests/stringable_automatic_implementation.phpt @@ -0,0 +1,35 @@ +--TEST-- +Stringable is automatically implemented +--FILE-- +<?php + +class Test { + public function __toString() { + return "foo"; + } +} + +var_dump(new Test instanceof Stringable); +var_dump((new ReflectionClass(Test::class))->getInterfaceNames()); + +class Test2 extends Test { + public function __toString() { + return "bar"; + } +} + +var_dump(new Test2 instanceof Stringable); +var_dump((new ReflectionClass(Test2::class))->getInterfaceNames()); + +?> +--EXPECT-- +bool(true) +array(1) { + [0]=> + string(10) "Stringable" +} +bool(true) +array(1) { + [0]=> + string(10) "Stringable" +} diff --git a/Zend/tests/type_declarations/variance/stringable.phpt b/Zend/tests/type_declarations/variance/stringable.phpt new file mode 100644 index 0000000000000..a132080106f9e --- /dev/null +++ b/Zend/tests/type_declarations/variance/stringable.phpt @@ -0,0 +1,17 @@ +--TEST-- +Automatic Stringable implementation participates in variance +--FILE-- +<?php + +class Foo { + public function test(): Stringable {} +} +class Bar extends Foo { + public function test(): Bar {} + public function __toString() {} +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cbf5ebfc02445..0abf274dbd25e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6066,6 +6066,24 @@ static void zend_check_magic_method_attr(uint32_t attr, const char* method, zend } /* }}} */ +static void add_stringable_interface(zend_class_entry *ce) { + for (uint32_t i = 0; i < ce->num_interfaces; i++) { + if (zend_string_equals_literal(ce->interface_names[i].lc_name, "stringable")) { + /* Interface already explicitly implemented */ + return; + } + } + + ce->num_interfaces++; + ce->interface_names = + erealloc(ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces); + // TODO: Add known interned strings instead? + ce->interface_names[ce->num_interfaces - 1].name = + zend_string_init("Stringable", sizeof("Stringable") - 1, 0); + ce->interface_names[ce->num_interfaces - 1].lc_name = + zend_string_init("stringable", sizeof("stringable") - 1, 0); +} + void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */ { zend_class_entry *ce = CG(active_class_entry); @@ -6147,6 +6165,7 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { zend_check_magic_method_attr(fn_flags, "__toString", 0); ce->__tostring = (zend_function *) op_array; + add_stringable_interface(ce); } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { zend_check_magic_method_attr(fn_flags, "__invoke", 0); } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { @@ -6680,6 +6699,10 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ CG(active_class_entry) = ce; + if (implements_ast) { + zend_compile_implements(implements_ast); + } + zend_compile_stmt(stmt_ast); /* Reset lineno for final opcodes and errors */ @@ -6719,10 +6742,6 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } } - if (implements_ast) { - zend_compile_implements(implements_ast); - } - if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { zend_verify_abstract_class(ce); } diff --git a/ext/spl/tests/class_implements_variation1.phpt b/ext/spl/tests/class_implements_variation1.phpt index 65fbe1a58a60b..5c998c74944c8 100644 --- a/ext/spl/tests/class_implements_variation1.phpt +++ b/ext/spl/tests/class_implements_variation1.phpt @@ -184,7 +184,9 @@ Error: 2 - class_implements(): Class does not exist and could not be loaded, %s bool(false) --instance of classWithToString-- -array(0) { +array(1) { + ["Stringable"]=> + string(10) "Stringable" } --instance of classWithoutToString--