Commit 8a8f4752a3b for php
commit 8a8f4752a3b877265f8788bc121e20f9c1a2c7b8
Author: Jorg Sowa <jorg.sowa@gmail.com>
Date: Wed Nov 11 10:30:50 2026 +0100
Fix AST printing dropping readonly on promoted parameters (GH-25207)
Closes GH-25207
diff --git a/NEWS b/NEWS
index 2986eaec7c3..9397cd352ab 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ PHP NEWS
. Fixed use-after-free when the error handler releases a string while an
"Illegal string offset" warning is raised for its offset in a read, ?? or
nested isset()/empty(). (Jorg Sowa)
+ . Fixed AST printing dropping readonly on promoted constructor parameters.
+ (Jorg Sowa)
- Curl:
. Fixed curl_reset() retaining CURLOPT_PRIVATE after reset. (lacatoire)
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 7d6038a194d..0f20becf045 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -2627,6 +2627,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
zend_ast_export_attributes(str, ast->child[3], indent, 0);
}
zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CPP);
+ if (ast->attr & ZEND_ACC_READONLY) {
+ smart_str_appends(str, "readonly ");
+ }
if (ast->child[0]) {
zend_ast_export_type(str, ast->child[0], indent);
smart_str_appendc(str, ' ');
diff --git a/ext/zend_test/tests/compile_to_ast/readonly_promoted.phpt b/ext/zend_test/tests/compile_to_ast/readonly_promoted.phpt
new file mode 100644
index 00000000000..c038ce47d21
--- /dev/null
+++ b/ext/zend_test/tests/compile_to_ast/readonly_promoted.phpt
@@ -0,0 +1,28 @@
+--TEST--
+AST can be recreated (readonly promoted constructor parameters)
+--EXTENSIONS--
+zend_test
+--FILE--
+<?php
+
+class Foo {
+ public function __construct(
+ public readonly int $publicReadonly,
+ readonly int $implicitlyPublicReadonly,
+ protected private(set) readonly array $asymmetricReadonly = [],
+ #[Attr] private readonly ?string $attributedReadonly = null,
+ public int $notReadonly = 1,
+ ) {}
+}
+
+echo zend_test_compile_to_ast( file_get_contents( __FILE__ ) );
+
+?>
+--EXPECT--
+class Foo {
+ public function __construct(public readonly int $publicReadonly, readonly int $implicitlyPublicReadonly, protected private(set) readonly array $asymmetricReadonly = [], #[Attr] private readonly ?string $attributedReadonly = null, public int $notReadonly = 1) {
+ }
+
+}
+
+echo zend_test_compile_to_ast(file_get_contents(__FILE__));