Skip to content

Commit 9e775db

Browse files
Define Stringable with __toString():string method
1 parent c06850b commit 9e775db

36 files changed

+282
-263
lines changed

Diff for: Zend/tests/bug26166.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@ try {
6464
--EXPECT--
6565
Hello World!
6666
===NONE===
67-
Method NoneTest::__toString() must return a string value
67+
Return value of NoneTest::__toString() must be of type string, none returned
6868
===THROW===
6969
This is an error!

Diff for: Zend/tests/list_keyed_evaluation_order.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests
44

5-
class Stringable
5+
class StringCapable
66
{
77
private $name;
88
public function __construct(string $name) {

Diff for: Zend/tests/list_keyed_evaluation_order.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ list() with keys, evaluation order
55

66
require_once "list_keyed_evaluation_order.inc";
77

8-
$a = new Stringable("A");
9-
$c = new Stringable("C");
8+
$a = new StringCapable("A");
9+
$c = new StringCapable("C");
1010

1111
$e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"]));
1212

Diff for: Zend/tests/list_keyed_evaluation_order_nested.phpt

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ list() with keys, evaluation order: nested
55

66
require_once "list_keyed_evaluation_order.inc";
77

8-
$a = new Stringable("A");
9-
$c = new Stringable("C");
10-
$f = new Stringable("F");
11-
$g = new Stringable("G");
12-
$i = new Stringable("I");
8+
$a = new StringCapable("A");
9+
$c = new StringCapable("C");
10+
$f = new StringCapable("F");
11+
$g = new StringCapable("G");
12+
$i = new StringCapable("I");
1313

1414
$k = new IndexableRetrievable("K", new Indexable([
1515
"A" => "offset value for A",

Diff for: Zend/tests/type_declarations/scalar_basic.phpt

+6-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ $functions = [
1919
'bool' => function (bool $b) { return $b; }
2020
];
2121

22-
class Stringable {
22+
class StringCapable implements Stringable {
2323
public function __toString() {
2424
return "foobar";
2525
}
@@ -40,7 +40,7 @@ $values = [
4040
NULL,
4141
[],
4242
new StdClass,
43-
new Stringable,
43+
new StringCapable,
4444
fopen("data:text/plain,foobar", "r")
4545
];
4646

@@ -106,7 +106,7 @@ int(0)
106106
}
107107
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
108108

109-
*** Trying object(Stringable)#%s (0) {
109+
*** Trying object(StringCapable)#%s (0) {
110110
}
111111
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
112112

@@ -160,7 +160,7 @@ float(0)
160160
}
161161
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
162162

163-
*** Trying object(Stringable)#%s (0) {
163+
*** Trying object(StringCapable)#%s (0) {
164164
}
165165
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
166166

@@ -213,7 +213,7 @@ string(0) ""
213213
}
214214
*** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d
215215

216-
*** Trying object(Stringable)#%s (0) {
216+
*** Trying object(StringCapable)#%s (0) {
217217
}
218218
string(6) "foobar"
219219

@@ -266,7 +266,7 @@ bool(false)
266266
}
267267
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
268268

269-
*** Trying object(Stringable)#%s (0) {
269+
*** Trying object(StringCapable)#%s (0) {
270270
}
271271
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
272272

Diff for: Zend/tests/type_declarations/scalar_return_basic.phpt

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ $functions = [
2121
'bool' => function ($b): bool { return $b; }
2222
];
2323

24-
class Stringable {
24+
class StringCapable {
2525
public function __toString() {
2626
return "foobar";
2727
}
@@ -42,7 +42,7 @@ $values = [
4242
NULL,
4343
[],
4444
new StdClass,
45-
new Stringable,
45+
new StringCapable,
4646
fopen("data:text/plain,foobar", "r")
4747
];
4848

@@ -94,7 +94,7 @@ int(0)
9494
*** Trying object(stdClass)#6 (0) {
9595
}
9696
*** Caught Return value of {closure}() must be of type int, object returned in %s on line %d
97-
*** Trying object(Stringable)#7 (0) {
97+
*** Trying object(StringCapable)#7 (0) {
9898
}
9999
*** Caught Return value of {closure}() must be of type int, object returned in %s on line %d
100100
*** Trying resource(5) of type (stream)
@@ -132,7 +132,7 @@ float(0)
132132
*** Trying object(stdClass)#6 (0) {
133133
}
134134
*** Caught Return value of {closure}() must be of type float, object returned in %s on line %d
135-
*** Trying object(Stringable)#7 (0) {
135+
*** Trying object(StringCapable)#7 (0) {
136136
}
137137
*** Caught Return value of {closure}() must be of type float, object returned in %s on line %d
138138
*** Trying resource(5) of type (stream)
@@ -169,7 +169,7 @@ string(0) ""
169169
*** Trying object(stdClass)#6 (0) {
170170
}
171171
*** Caught Return value of {closure}() must be of type string, object returned in %s on line %d
172-
*** Trying object(Stringable)#7 (0) {
172+
*** Trying object(StringCapable)#7 (0) {
173173
}
174174
string(6) "foobar"
175175
*** Trying resource(5) of type (stream)
@@ -206,7 +206,7 @@ bool(false)
206206
*** Trying object(stdClass)#6 (0) {
207207
}
208208
*** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d
209-
*** Trying object(Stringable)#7 (0) {
209+
*** Trying object(StringCapable)#7 (0) {
210210
}
211211
*** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d
212212
*** Trying resource(5) of type (stream)

Diff for: Zend/tests/type_declarations/scalar_return_basic_64bit.phpt

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ $functions = [
2121
'bool' => function ($b): bool { return $b; }
2222
];
2323

24-
class Stringable {
24+
class StringCapable {
2525
public function __toString() {
2626
return "foobar";
2727
}
@@ -42,7 +42,7 @@ $values = [
4242
NULL,
4343
[],
4444
new StdClass,
45-
new Stringable,
45+
new StringCapable,
4646
fopen("data:text/plain,foobar", "r")
4747
];
4848

@@ -94,7 +94,7 @@ int(0)
9494
*** Trying object(stdClass)#6 (0) {
9595
}
9696
*** Caught Return value of {closure}() must be of type int, object returned in %s on line %d
97-
*** Trying object(Stringable)#7 (0) {
97+
*** Trying object(StringCapable)#7 (0) {
9898
}
9999
*** Caught Return value of {closure}() must be of type int, object returned in %s on line %d
100100
*** Trying resource(5) of type (stream)
@@ -132,7 +132,7 @@ float(0)
132132
*** Trying object(stdClass)#6 (0) {
133133
}
134134
*** Caught Return value of {closure}() must be of type float, object returned in %s on line %d
135-
*** Trying object(Stringable)#7 (0) {
135+
*** Trying object(StringCapable)#7 (0) {
136136
}
137137
*** Caught Return value of {closure}() must be of type float, object returned in %s on line %d
138138
*** Trying resource(5) of type (stream)
@@ -169,7 +169,7 @@ string(0) ""
169169
*** Trying object(stdClass)#6 (0) {
170170
}
171171
*** Caught Return value of {closure}() must be of type string, object returned in %s on line %d
172-
*** Trying object(Stringable)#7 (0) {
172+
*** Trying object(StringCapable)#7 (0) {
173173
}
174174
string(6) "foobar"
175175
*** Trying resource(5) of type (stream)
@@ -206,7 +206,7 @@ bool(false)
206206
*** Trying object(stdClass)#6 (0) {
207207
}
208208
*** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d
209-
*** Trying object(Stringable)#7 (0) {
209+
*** Trying object(StringCapable)#7 (0) {
210210
}
211211
*** Caught Return value of {closure}() must be of type bool, object returned in %s on line %d
212212
*** Trying resource(5) of type (stream)

Diff for: Zend/tests/type_declarations/scalar_strict.phpt

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ $functions = [
1313
'bool' => function (bool $b) { return $b; }
1414
];
1515

16-
class Stringable {
16+
class StringCapable {
1717
public function __toString() {
1818
return "foobar";
1919
}
@@ -34,7 +34,7 @@ $values = [
3434
NULL,
3535
[],
3636
new StdClass,
37-
new Stringable,
37+
new StringCapable,
3838
fopen("data:text/plain,foobar", "r")
3939
];
4040

@@ -100,7 +100,7 @@ int(2147483647)
100100
}
101101
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
102102

103-
*** Trying object(Stringable)#6 (0) {
103+
*** Trying object(StringCapable)#6 (0) {
104104
}
105105
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
106106

@@ -153,7 +153,7 @@ float(NAN)
153153
}
154154
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
155155

156-
*** Trying object(Stringable)#6 (0) {
156+
*** Trying object(StringCapable)#6 (0) {
157157
}
158158
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
159159

@@ -206,7 +206,7 @@ string(0) ""
206206
}
207207
*** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d
208208

209-
*** Trying object(Stringable)#6 (0) {
209+
*** Trying object(StringCapable)#6 (0) {
210210
}
211211
*** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d
212212

@@ -259,7 +259,7 @@ bool(false)
259259
}
260260
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
261261

262-
*** Trying object(Stringable)#6 (0) {
262+
*** Trying object(StringCapable)#6 (0) {
263263
}
264264
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
265265

Diff for: Zend/tests/type_declarations/scalar_strict_64bit.phpt

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ $functions = [
1313
'bool' => function (bool $b) { return $b; }
1414
];
1515

16-
class Stringable {
16+
class StringCapable {
1717
public function __toString() {
1818
return "foobar";
1919
}
@@ -34,7 +34,7 @@ $values = [
3434
NULL,
3535
[],
3636
new StdClass,
37-
new Stringable,
37+
new StringCapable,
3838
fopen("data:text/plain,foobar", "r")
3939
];
4040

@@ -100,7 +100,7 @@ int(9223372036854775807)
100100
}
101101
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
102102

103-
*** Trying object(Stringable)#6 (0) {
103+
*** Trying object(StringCapable)#6 (0) {
104104
}
105105
*** Caught {closure}(): Argument #1 ($i) must be of type int, object given, called in %s on line %d
106106

@@ -153,7 +153,7 @@ float(NAN)
153153
}
154154
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
155155

156-
*** Trying object(Stringable)#6 (0) {
156+
*** Trying object(StringCapable)#6 (0) {
157157
}
158158
*** Caught {closure}(): Argument #1 ($f) must be of type float, object given, called in %s on line %d
159159

@@ -206,7 +206,7 @@ string(0) ""
206206
}
207207
*** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d
208208

209-
*** Trying object(Stringable)#6 (0) {
209+
*** Trying object(StringCapable)#6 (0) {
210210
}
211211
*** Caught {closure}(): Argument #1 ($s) must be of type string, object given, called in %s on line %d
212212

@@ -259,7 +259,7 @@ bool(false)
259259
}
260260
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
261261

262-
*** Trying object(Stringable)#6 (0) {
262+
*** Trying object(StringCapable)#6 (0) {
263263
}
264264
*** Caught {closure}(): Argument #1 ($b) must be of type bool, object given, called in %s on line %d
265265

Diff for: Zend/zend_compile.c

+12-7
Original file line numberDiff line numberDiff line change
@@ -5714,22 +5714,26 @@ static zend_bool zend_is_valid_default_value(zend_type type, zval *value)
57145714
return 0;
57155715
}
57165716

5717-
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
5717+
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fallback_return_type) /* {{{ */
57185718
{
57195719
zend_ast_list *list = zend_ast_get_list(ast);
57205720
uint32_t i;
57215721
zend_op_array *op_array = CG(active_op_array);
57225722
zend_arg_info *arg_infos;
57235723
zend_string *optional_param = NULL;
57245724

5725-
if (return_type_ast) {
5725+
if (return_type_ast || fallback_return_type) {
57265726
/* Use op_array->arg_info[-1] for return type */
57275727
arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
57285728
arg_infos->name = NULL;
5729-
arg_infos->type = zend_compile_typename(
5730-
return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0);
5731-
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
5732-
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
5729+
if (return_type_ast) {
5730+
arg_infos->type = zend_compile_typename(
5731+
return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0);
5732+
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
5733+
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
5734+
} else {
5735+
arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
5736+
}
57335737
arg_infos++;
57345738
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
57355739
} else {
@@ -6294,7 +6298,8 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
62946298
zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
62956299
}
62966300

6297-
zend_compile_params(params_ast, return_type_ast);
6301+
zend_compile_params(params_ast, return_type_ast,
6302+
is_method && zend_string_equals_literal_ci(decl->name, "__toString") ? IS_STRING : 0);
62986303
if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
62996304
zend_mark_function_as_generator();
63006305
zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);

Diff for: Zend/zend_exceptions.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,6 @@ static const zend_function_entry zend_funcs_throwable[] = {
763763
ZEND_ABSTRACT_ME(throwable, getTrace, arginfo_class_Throwable_getTrace)
764764
ZEND_ABSTRACT_ME(throwable, getPrevious, arginfo_class_Throwable_getPrevious)
765765
ZEND_ABSTRACT_ME(throwable, getTraceAsString, arginfo_class_Throwable_getTraceAsString)
766-
ZEND_ABSTRACT_ME(throwable, __toString, arginfo_class_Throwable___toString)
767766
ZEND_FE_END
768767
};
769768
/* }}} */
@@ -805,6 +804,7 @@ void zend_register_default_exception(void) /* {{{ */
805804
zend_class_entry ce;
806805

807806
REGISTER_MAGIC_INTERFACE(throwable, Throwable);
807+
zend_class_implements(zend_ce_throwable, 1, zend_ce_stringable);
808808

809809
memcpy(&default_exception_handlers, &std_object_handlers, sizeof(zend_object_handlers));
810810
default_exception_handlers.clone_obj = NULL;

0 commit comments

Comments
 (0)