diff --git a/UPGRADING b/UPGRADING index 30611b1013219..5174a2e52f6f1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -130,6 +130,18 @@ PHP 8.0 UPGRADE NOTES exception. . Some "Only variables should be passed by reference" notices have been converted to "Cannot pass parameter by reference" exception. + . The generated name for anonymous classes has changed. It will now include + the name of the first parent or interface: + + new class extends ParentClass {}; + // -> ParentClass@anonymous + new class implements FirstInterface, SecondInterface {}; + // -> FirstInterface@anonymous + new class {}; + // -> class@anonymous + + The name shown above is still followed by a null byte and and a unique + suffix. - COM: . Removed the ability to import case-insensitive constants from type @@ -386,7 +398,6 @@ PHP 8.0 UPGRADE NOTES writing `Foo::BAR::$baz` is now allowed. RFC: https://wiki.php.net/rfc/variable_syntax_tweaks - - Date: . Added DateTime::createFromInterface() and DateTimeImmutable::createFromInterface(). diff --git a/Zend/tests/anon_class_name.phpt b/Zend/tests/anon_class_name.phpt new file mode 100644 index 0000000000000..36f613d707b1c --- /dev/null +++ b/Zend/tests/anon_class_name.phpt @@ -0,0 +1,30 @@ +--TEST-- +Generated names for anonymous classes +--FILE-- + +--EXPECT-- +class@anonymous +DeclaringNS\Test1@anonymous +DeclaringNS\Test1@anonymous +DeclaringNS\Test2@anonymous +DeclaringNS\Test2@anonymous diff --git a/Zend/tests/object_types/return_type_in_class.phpt b/Zend/tests/object_types/return_type_in_class.phpt index c4c1dc05160ee..3edb015df756c 100644 --- a/Zend/tests/object_types/return_type_in_class.phpt +++ b/Zend/tests/object_types/return_type_in_class.phpt @@ -18,8 +18,8 @@ $three = new class extends Two { }; $three->a(); --EXPECTF-- -Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13 +Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d Stack trace: -#0 %s(16): class@anonymous->a() +#0 %s(%d): Two@anonymous->a() #1 {main} thrown in %s on line 13 diff --git a/Zend/tests/object_types/return_type_inheritance_in_class.phpt b/Zend/tests/object_types/return_type_inheritance_in_class.phpt index a7316136fb778..23528531ec563 100644 --- a/Zend/tests/object_types/return_type_inheritance_in_class.phpt +++ b/Zend/tests/object_types/return_type_inheritance_in_class.phpt @@ -18,8 +18,8 @@ $three = new class extends Two { }; $three->a(); --EXPECTF-- -Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13 +Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d Stack trace: -#0 %s(16): class@anonymous->a() +#0 %s(%d): Two@anonymous->a() #1 {main} thrown in %s on line 13 diff --git a/Zend/tests/object_types/return_type_inheritance_in_interface.phpt b/Zend/tests/object_types/return_type_inheritance_in_interface.phpt index 4c8f6c08affbb..793cc980aa6ae 100644 --- a/Zend/tests/object_types/return_type_inheritance_in_interface.phpt +++ b/Zend/tests/object_types/return_type_inheritance_in_interface.phpt @@ -18,8 +18,8 @@ $three = new class implements Two { }; $three->a(); --EXPECTF-- -Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13 +Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d Stack trace: -#0 %s(16): class@anonymous->a() +#0 %s(%d): Two@anonymous->a() #1 {main} thrown in %s on line 13 diff --git a/Zend/tests/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning_013.phpt index d9e7dd82f5c7c..401edb512b97e 100644 --- a/Zend/tests/temporary_cleaning_013.phpt +++ b/Zend/tests/temporary_cleaning_013.phpt @@ -288,10 +288,10 @@ caught Exception 12 caught Exception 13 caught Exception 14 -Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d +Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d caught Exception 15 -Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d +Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d caught Exception 16 caught Exception 17 caught Exception 18 diff --git a/Zend/tests/type_declarations/typed_properties_065.phpt b/Zend/tests/type_declarations/typed_properties_065.phpt index d81b51d049d64..7a1dd54894b34 100644 --- a/Zend/tests/type_declarations/typed_properties_065.phpt +++ b/Zend/tests/type_declarations/typed_properties_065.phpt @@ -61,11 +61,11 @@ offsetSet(1e50) int(1) int(0) int(-1) -Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value +Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value integer -Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value +Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value integer -Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value +Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value integer -Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value +Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value integer diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 58fb3377d2cfc..bc0a7dfdaeacf 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6569,14 +6569,25 @@ void zend_compile_implements(zend_ast *ast) /* {{{ */ } /* }}} */ -static zend_string *zend_generate_anon_class_name(uint32_t start_lineno) /* {{{ */ +static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl) { zend_string *filename = CG(active_op_array)->filename; - zend_string *result = zend_strpprintf(0, "class@anonymous%c%s:%" PRIu32 "$%" PRIx32, - '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++); + uint32_t start_lineno = decl->start_lineno; + + /* Use parent or first interface as prefix. */ + zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS); + if (decl->child[0]) { + prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name"); + } else if (decl->child[1]) { + zend_ast_list *list = zend_ast_get_list(decl->child[1]); + prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name"); + } + + zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32, + ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++); + zend_string_release(prefix); return zend_new_interned_string(result); } -/* }}} */ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ { @@ -6613,7 +6624,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS); } else { - name = zend_generate_anon_class_name(decl->start_lineno); + name = zend_generate_anon_class_name(decl); lcname = zend_string_tolower(name); } lcname = zend_new_interned_string(lcname); diff --git a/ext/opcache/tests/bug78937_1.phpt b/ext/opcache/tests/bug78937_1.phpt index bc285f107b98d..0572e521aa53d 100644 --- a/ext/opcache/tests/bug78937_1.phpt +++ b/ext/opcache/tests/bug78937_1.phpt @@ -19,7 +19,7 @@ var_dump(foo()); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3 diff --git a/ext/opcache/tests/bug78937_2.phpt b/ext/opcache/tests/bug78937_2.phpt index a20c07d231e3f..90aaa4388341b 100644 --- a/ext/opcache/tests/bug78937_2.phpt +++ b/ext/opcache/tests/bug78937_2.phpt @@ -20,6 +20,6 @@ var_dump(foo()); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 -object(class@anonymous)#%d (0) { +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +object(Bar@anonymous)#%d (0) { } diff --git a/ext/opcache/tests/bug78937_3.phpt b/ext/opcache/tests/bug78937_3.phpt index 16f7b80a4035f..81821e3109a75 100644 --- a/ext/opcache/tests/bug78937_3.phpt +++ b/ext/opcache/tests/bug78937_3.phpt @@ -18,7 +18,7 @@ var_dump(foo()); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:3 Stack trace: diff --git a/ext/opcache/tests/bug78937_4.phpt b/ext/opcache/tests/bug78937_4.phpt index 2ad86870de85b..86c38a6d98f4e 100644 --- a/ext/opcache/tests/bug78937_4.phpt +++ b/ext/opcache/tests/bug78937_4.phpt @@ -20,6 +20,6 @@ var_dump(new Foo); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6 diff --git a/ext/opcache/tests/bug78937_5.phpt b/ext/opcache/tests/bug78937_5.phpt index 3502699750e39..bb83408d90e36 100644 --- a/ext/opcache/tests/bug78937_5.phpt +++ b/ext/opcache/tests/bug78937_5.phpt @@ -21,6 +21,6 @@ var_dump(new Foo); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 object(Foo)#%d (0) { } diff --git a/ext/opcache/tests/bug78937_6.phpt b/ext/opcache/tests/bug78937_6.phpt index ec1cc2d2772a5..6e4d7060b3c76 100644 --- a/ext/opcache/tests/bug78937_6.phpt +++ b/ext/opcache/tests/bug78937_6.phpt @@ -19,7 +19,7 @@ var_dump(new Foo); --EXPECTF-- Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 -Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:6 Stack trace: diff --git a/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt b/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt index 8671c2500bd54..df7fb4207333c 100644 --- a/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt +++ b/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt @@ -11,7 +11,7 @@ class Base {} $check = function () { $base = Base::class; foreach (get_declared_classes() as $class) { - if (strpos($class, 'class@anonymous') === false) { + if (strpos($class, '@anonymous') === false) { continue; } echo "Checking for $class\n"; @@ -30,6 +30,6 @@ echo "Done\n"; ?> --EXPECTF-- After first check -Checking for class@%s +Checking for Base@%s true Done diff --git a/ext/standard/tests/class_object/bug78638.phpt b/ext/standard/tests/class_object/bug78638.phpt index 088e7c4c1f083..76315ee1c568a 100644 --- a/ext/standard/tests/class_object/bug78638.phpt +++ b/ext/standard/tests/class_object/bug78638.phpt @@ -6,4 +6,4 @@ $c = new class('bar') extends __PHP_Incomplete_Class { }; ?> --EXPECTF-- -Fatal error: Class class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %sbug78638.php on line %d +Fatal error: Class __PHP_Incomplete_Class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %s on line %d diff --git a/ext/standard/tests/class_object/get_object_vars_variation_004.phpt b/ext/standard/tests/class_object/get_object_vars_variation_004.phpt index f52b3fed78e65..902149ea0ac4c 100644 Binary files a/ext/standard/tests/class_object/get_object_vars_variation_004.phpt and b/ext/standard/tests/class_object/get_object_vars_variation_004.phpt differ