Skip to content

Commit 72bd559

Browse files
committed
Improve generated names for anonymous classes
In order of preference, the generated name will be: new class extends ParentClass {}; // -> ParentClass@anonymous new class implements FirstInterface, SecondInterface {}; // -> FirstInterface@anonymous new class {}; // -> class@anonymous This is intended to display a more useful class name in error messages and stack traces, and thus make debugging easier. Closes GH-5153.
1 parent 4344385 commit 72bd559

17 files changed

+80
-28
lines changed

Diff for: UPGRADING

+12-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ PHP 8.0 UPGRADE NOTES
130130
exception.
131131
. Some "Only variables should be passed by reference" notices have been converted
132132
to "Cannot pass parameter by reference" exception.
133+
. The generated name for anonymous classes has changed. It will now include
134+
the name of the first parent or interface:
135+
136+
new class extends ParentClass {};
137+
// -> ParentClass@anonymous
138+
new class implements FirstInterface, SecondInterface {};
139+
// -> FirstInterface@anonymous
140+
new class {};
141+
// -> class@anonymous
142+
143+
The name shown above is still followed by a null byte and and a unique
144+
suffix.
133145

134146
- COM:
135147
. Removed the ability to import case-insensitive constants from type
@@ -386,7 +398,6 @@ PHP 8.0 UPGRADE NOTES
386398
writing `Foo::BAR::$baz` is now allowed.
387399
RFC: https://wiki.php.net/rfc/variable_syntax_tweaks
388400

389-
390401
- Date:
391402
. Added DateTime::createFromInterface() and
392403
DateTimeImmutable::createFromInterface().

Diff for: Zend/tests/anon_class_name.phpt

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Generated names for anonymous classes
3+
--FILE--
4+
<?php
5+
6+
namespace DeclaringNS {
7+
class Test1 {}
8+
interface Test2 {}
9+
interface Test3 {}
10+
}
11+
12+
namespace UsingNS {
13+
function print_name(object $obj) {
14+
echo strstr(get_class($obj), "\0", true), "\n";
15+
}
16+
17+
print_name(new class {});
18+
print_name(new class extends \DeclaringNS\Test1 {});
19+
print_name(new class extends \DeclaringNS\Test1 implements \DeclaringNS\Test2 {});
20+
print_name(new class implements \DeclaringNS\Test2 {});
21+
print_name(new class implements \DeclaringNS\Test2, \DeclaringNS\Test3 {});
22+
}
23+
24+
?>
25+
--EXPECT--
26+
class@anonymous
27+
DeclaringNS\Test1@anonymous
28+
DeclaringNS\Test1@anonymous
29+
DeclaringNS\Test2@anonymous
30+
DeclaringNS\Test2@anonymous

Diff for: Zend/tests/object_types/return_type_in_class.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ $three = new class extends Two {
1818
};
1919
$three->a();
2020
--EXPECTF--
21-
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
21+
Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
2222
Stack trace:
23-
#0 %s(16): class@anonymous->a()
23+
#0 %s(%d): Two@anonymous->a()
2424
#1 {main}
2525
thrown in %s on line 13

Diff for: Zend/tests/object_types/return_type_inheritance_in_class.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ $three = new class extends Two {
1818
};
1919
$three->a();
2020
--EXPECTF--
21-
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
21+
Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
2222
Stack trace:
23-
#0 %s(16): class@anonymous->a()
23+
#0 %s(%d): Two@anonymous->a()
2424
#1 {main}
2525
thrown in %s on line 13

Diff for: Zend/tests/object_types/return_type_inheritance_in_interface.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ $three = new class implements Two {
1818
};
1919
$three->a();
2020
--EXPECTF--
21-
Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
21+
Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
2222
Stack trace:
23-
#0 %s(16): class@anonymous->a()
23+
#0 %s(%d): Two@anonymous->a()
2424
#1 {main}
2525
thrown in %s on line 13

Diff for: Zend/tests/temporary_cleaning_013.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,10 @@ caught Exception 12
288288
caught Exception 13
289289
caught Exception 14
290290

291-
Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d
291+
Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
292292
caught Exception 15
293293

294-
Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d
294+
Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
295295
caught Exception 16
296296
caught Exception 17
297297
caught Exception 18

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ offsetSet(1e50)
6161
int(1)
6262
int(0)
6363
int(-1)
64-
Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value
64+
Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value
6565
integer
66-
Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value
66+
Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value
6767
integer
68-
Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value
68+
Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value
6969
integer
70-
Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value
70+
Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value
7171
integer

Diff for: Zend/zend_compile.c

+16-5
Original file line numberDiff line numberDiff line change
@@ -6569,14 +6569,25 @@ void zend_compile_implements(zend_ast *ast) /* {{{ */
65696569
}
65706570
/* }}} */
65716571

6572-
static zend_string *zend_generate_anon_class_name(uint32_t start_lineno) /* {{{ */
6572+
static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
65736573
{
65746574
zend_string *filename = CG(active_op_array)->filename;
6575-
zend_string *result = zend_strpprintf(0, "class@anonymous%c%s:%" PRIu32 "$%" PRIx32,
6576-
'\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
6575+
uint32_t start_lineno = decl->start_lineno;
6576+
6577+
/* Use parent or first interface as prefix. */
6578+
zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
6579+
if (decl->child[0]) {
6580+
prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
6581+
} else if (decl->child[1]) {
6582+
zend_ast_list *list = zend_ast_get_list(decl->child[1]);
6583+
prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
6584+
}
6585+
6586+
zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
6587+
ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
6588+
zend_string_release(prefix);
65776589
return zend_new_interned_string(result);
65786590
}
6579-
/* }}} */
65806591

65816592
zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
65826593
{
@@ -6613,7 +6624,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
66136624

66146625
zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
66156626
} else {
6616-
name = zend_generate_anon_class_name(decl->start_lineno);
6627+
name = zend_generate_anon_class_name(decl);
66176628
lcname = zend_string_tolower(name);
66186629
}
66196630
lcname = zend_new_interned_string(lcname);

Diff for: ext/opcache/tests/bug78937_1.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ var_dump(foo());
1919
--EXPECTF--
2020
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2121

22-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
22+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
2323

2424
Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3
2525

Diff for: ext/opcache/tests/bug78937_2.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ var_dump(foo());
2020
--EXPECTF--
2121
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2222

23-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
24-
object(class@anonymous)#%d (0) {
23+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
24+
object(Bar@anonymous)#%d (0) {
2525
}

Diff for: ext/opcache/tests/bug78937_3.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var_dump(foo());
1818
--EXPECTF--
1919
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2020

21-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
21+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
2222

2323
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:3
2424
Stack trace:

Diff for: ext/opcache/tests/bug78937_4.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ var_dump(new Foo);
2020
--EXPECTF--
2121
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2222

23-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
23+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
2424

2525
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6

Diff for: ext/opcache/tests/bug78937_5.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ var_dump(new Foo);
2121
--EXPECTF--
2222
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2323

24-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
24+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
2525
object(Foo)#%d (0) {
2626
}

Diff for: ext/opcache/tests/bug78937_6.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ var_dump(new Foo);
1919
--EXPECTF--
2020
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
2121

22-
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
22+
Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
2323

2424
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:6
2525
Stack trace:

Diff for: ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Base {}
1111
$check = function () {
1212
$base = Base::class;
1313
foreach (get_declared_classes() as $class) {
14-
if (strpos($class, 'class@anonymous') === false) {
14+
if (strpos($class, '@anonymous') === false) {
1515
continue;
1616
}
1717
echo "Checking for $class\n";
@@ -30,6 +30,6 @@ echo "Done\n";
3030
?>
3131
--EXPECTF--
3232
After first check
33-
Checking for class@%s
33+
Checking for Base@%s
3434
true
3535
Done

Diff for: ext/standard/tests/class_object/bug78638.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ $c = new class('bar') extends __PHP_Incomplete_Class {
66
};
77
?>
88
--EXPECTF--
9-
Fatal error: Class class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %sbug78638.php on line %d
9+
Fatal error: Class __PHP_Incomplete_Class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %s on line %d
Binary file not shown.

0 commit comments

Comments
 (0)