From fbabf0cbfb9e609e8936ce038f0d9e991b054447 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Sat, 4 Jul 2026 14:02:10 +0700 Subject: [PATCH 1/3] Allowed defaults on readonly properties --- .../readonly_class_inheritance_success.phpt | 11 +++++ .../readonly_with_property_default.phpt | 36 +++++++++++++++++ .../readonly_with_property_default_trait.phpt | 18 +++++++++ .../readonly_clone_success1.phpt | 30 ++++++++++++++ .../readonly_props/readonly_modification.phpt | 16 ++++++++ .../readonly_props/readonly_trait_match.phpt | 13 ++++++ .../readonly_props/readonly_with_default.phpt | 30 +++++++++++++- ...ly_with_default_asymmetric_visibility.phpt | 33 +++++++++++++++ .../readonly_with_default_inheritance.phpt | 40 +++++++++++++++++++ .../readonly_with_default_interface.phpt | 29 ++++++++++++++ .../readonly_with_default_reflection.phpt | 35 ++++++++++++++++ .../readonly_with_default_trait_mismatch.phpt | 20 ++++++++++ Zend/tests/readonly_props/serialization.phpt | 29 ++++++++++++++ Zend/tests/readonly_props/unset.phpt | 31 ++++++++++++++ Zend/zend_compile.c | 5 --- 15 files changed, 369 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/readonly_classes/readonly_with_property_default.phpt create mode 100644 Zend/tests/readonly_classes/readonly_with_property_default_trait.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_inheritance.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_interface.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_reflection.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_trait_mismatch.phpt diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt index 33e73554ce01..133152ca6e91 100644 --- a/Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt @@ -5,11 +5,22 @@ Readonly class can extend a readonly class readonly class Foo { + public int $prop = 1; } readonly class Bar extends Foo { + public int $prop = 2; } +readonly class Baz extends Foo {} + +var_dump(new Foo()->prop); +var_dump(new Bar()->prop); +var_dump(new Baz()->prop); + ?> --EXPECT-- +int(1) +int(2) +int(1) diff --git a/Zend/tests/readonly_classes/readonly_with_property_default.phpt b/Zend/tests/readonly_classes/readonly_with_property_default.phpt new file mode 100644 index 000000000000..b6e38e23e8b0 --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_with_property_default.phpt @@ -0,0 +1,36 @@ +--TEST-- +Properties of a readonly class may have default values +--FILE-- +bar = 2; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + } +} + +$foo = new Foo(); +var_dump($foo->bar); +var_dump($foo->nullable); + +try { + $foo->bar = 3; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot modify readonly property Foo::$bar +int(1) +NULL +Cannot modify readonly property Foo::$bar diff --git a/Zend/tests/readonly_classes/readonly_with_property_default_trait.phpt b/Zend/tests/readonly_classes/readonly_with_property_default_trait.phpt new file mode 100644 index 000000000000..e96945e0992e --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_with_property_default_trait.phpt @@ -0,0 +1,18 @@ +--TEST-- +Readonly class may use readonly trait property with default value +--FILE-- +prop); + +?> +--EXPECT-- +int(2) diff --git a/Zend/tests/readonly_props/readonly_clone_success1.phpt b/Zend/tests/readonly_props/readonly_clone_success1.phpt index 72cd9e9622b3..ab6ee3157332 100644 --- a/Zend/tests/readonly_props/readonly_clone_success1.phpt +++ b/Zend/tests/readonly_props/readonly_clone_success1.phpt @@ -23,6 +23,24 @@ var_dump($foo2); var_dump(clone $foo2); +class FooWithDefault { + public readonly int $bar = 1; + + public function __clone() + { + $this->bar++; + } +} + +$fooWithDefault = new FooWithDefault(); + +var_dump(clone $fooWithDefault); + +$fooWithDefault2 = clone $fooWithDefault; +var_dump($fooWithDefault2); + +var_dump(clone $fooWithDefault2); + ?> --EXPECTF-- object(Foo)#%d (%d) { @@ -37,3 +55,15 @@ object(Foo)#%d (%d) { ["bar"]=> int(3) } +object(FooWithDefault)#%d (%d) { + ["bar"]=> + int(2) +} +object(FooWithDefault)#%d (%d) { + ["bar"]=> + int(2) +} +object(FooWithDefault)#%d (%d) { + ["bar"]=> + int(3) +} diff --git a/Zend/tests/readonly_props/readonly_modification.phpt b/Zend/tests/readonly_props/readonly_modification.phpt index bd04a203be19..67199cb6ec1a 100644 --- a/Zend/tests/readonly_props/readonly_modification.phpt +++ b/Zend/tests/readonly_props/readonly_modification.phpt @@ -14,6 +14,18 @@ class Test { } } +class TestWithDefault { + public readonly int $prop = 1; + + public function __construct() { + try { + $this->prop = 2; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + } +} + function byRef(&$ref) {} $test = new Test; @@ -66,6 +78,8 @@ try { echo $e->getMessage(), "\n"; } +var_dump(new TestWithDefault()->prop); + ?> --EXPECT-- int(1) @@ -80,3 +94,5 @@ array(0) { } Cannot indirectly modify readonly property Test::$prop2 Cannot indirectly modify readonly property Test::$prop2 +Cannot modify readonly property TestWithDefault::$prop +int(1) diff --git a/Zend/tests/readonly_props/readonly_trait_match.phpt b/Zend/tests/readonly_props/readonly_trait_match.phpt index 00aa6349aa14..36f2e11ec2bc 100644 --- a/Zend/tests/readonly_props/readonly_trait_match.phpt +++ b/Zend/tests/readonly_props/readonly_trait_match.phpt @@ -13,7 +13,20 @@ class C { use T1, T2; } +trait TDefault1 { + public readonly int $prop = 1; +} +trait TDefault2 { + public readonly int $prop = 1; +} +class CDefault { + use TDefault1, TDefault2; +} + +var_dump(new CDefault()->prop); + ?> ===DONE=== --EXPECT-- +int(1) ===DONE=== diff --git a/Zend/tests/readonly_props/readonly_with_default.phpt b/Zend/tests/readonly_props/readonly_with_default.phpt index 12afe5cde153..84977bfda1c3 100644 --- a/Zend/tests/readonly_props/readonly_with_default.phpt +++ b/Zend/tests/readonly_props/readonly_with_default.phpt @@ -3,11 +3,26 @@ Readonly property with default value --FILE-- 2]; + public readonly E $enum = E::Case; + public readonly string $enumString = E::Case->name; } $test = new Test; +var_dump($test->prop); +var_dump($test->className); +var_dump($test->nullable); +var_dump($test->array); +var_dump($test->enum); +var_dump($test->enumString); try { $test->prop = 2; } catch (Error $e) { @@ -15,5 +30,16 @@ try { } ?> ---EXPECTF-- -Fatal error: Readonly property Test::$prop cannot have default value in %s on line %d +--EXPECT-- +int(1) +string(4) "Test" +NULL +array(2) { + [0]=> + int(1) + ["two"]=> + int(2) +} +enum(E::Case) +string(4) "Case" +Cannot modify readonly property Test::$prop diff --git a/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt b/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt new file mode 100644 index 000000000000..3d31f098f402 --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt @@ -0,0 +1,33 @@ +--TEST-- +Readonly property with default value and asymmetric visibility +--FILE-- +default, $test->private, $test->protected, $test->public); + +foreach (['default', 'private', 'protected', 'public'] as $prop) { + try { + $test->$prop = 42; + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(4) +Cannot modify readonly property Test::$default +Cannot modify readonly property Test::$private +Cannot modify readonly property Test::$protected +Cannot modify readonly property Test::$public diff --git a/Zend/tests/readonly_props/readonly_with_default_inheritance.phpt b/Zend/tests/readonly_props/readonly_with_default_inheritance.phpt new file mode 100644 index 000000000000..8b285dcdd769 --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_inheritance.phpt @@ -0,0 +1,40 @@ +--TEST-- +Readonly property with default value and inheritance +--FILE-- +prop; + } +} + +class PrivateChild extends PrivateParent { + public readonly int $prop = 4; +} + +var_dump(new ChildInherits()->prop); +var_dump(new ChildOverrides()->prop); + +$privateChild = new PrivateChild(); +var_dump($privateChild->getParentProp()); +var_dump($privateChild->prop); + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(4) diff --git a/Zend/tests/readonly_props/readonly_with_default_interface.phpt b/Zend/tests/readonly_props/readonly_with_default_interface.phpt new file mode 100644 index 000000000000..a20d869dc661 --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_interface.phpt @@ -0,0 +1,29 @@ +--TEST-- +Readonly property with default value satisfies get-only interface property +--FILE-- +prop); + +interface J { + public int $prop { get; set; } +} + +// does not satisfy set +class D implements J { + public readonly int $prop = 42; +} + +?> +--EXPECTF-- +int(42) + +Fatal error: Set access level of D::$prop must be omitted (as in class J) in %s on line %d diff --git a/Zend/tests/readonly_props/readonly_with_default_reflection.phpt b/Zend/tests/readonly_props/readonly_with_default_reflection.phpt new file mode 100644 index 000000000000..fd1df1ebff29 --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_reflection.phpt @@ -0,0 +1,35 @@ +--TEST-- +Reflection for readonly property with default value +--FILE-- +isReadOnly()); +var_dump($rp->hasDefaultValue()); +var_dump($rp->getDefaultValue()); +var_dump(new ReflectionClass(Foo::class)->getDefaultProperties()); + +$test = new Foo(); +try { + $rp->setValue($test, 2); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +bool(true) +bool(true) +int(1) +array(2) { + ["prop"]=> + int(1) + ["nullable"]=> + NULL +} +Cannot modify readonly property Foo::$prop diff --git a/Zend/tests/readonly_props/readonly_with_default_trait_mismatch.phpt b/Zend/tests/readonly_props/readonly_with_default_trait_mismatch.phpt new file mode 100644 index 000000000000..6668b1d860bb --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_trait_mismatch.phpt @@ -0,0 +1,20 @@ +--TEST-- +Readonly trait property default value mismatch +--FILE-- + +--EXPECTF-- +Fatal error: T1 and T2 define the same property ($prop) in the composition of C. However, the definition differs and is considered incompatible. Class was composed in %s on line %d diff --git a/Zend/tests/readonly_props/serialization.phpt b/Zend/tests/readonly_props/serialization.phpt index f9e1f364673f..f51fce199a63 100644 --- a/Zend/tests/readonly_props/serialization.phpt +++ b/Zend/tests/readonly_props/serialization.phpt @@ -17,6 +17,18 @@ var_dump(unserialize($s)); var_dump(unserialize("O:4:\"Test\":1:{s:4:\"prop\";i:2;}")); var_dump(unserialize("O:4:\"Test\":2:{s:4:\"prop\";i:2;s:4:\"prop\";i:3;}")); +class TestDefault { + public readonly int $prop = 1; +} + +var_dump($s = serialize(new TestDefault)); +var_dump(unserialize($s)); + +// Unserialization still bypasses normal readonly assignment semantics. +var_dump(unserialize("O:11:\"TestDefault\":0:{}")); +var_dump(unserialize("O:11:\"TestDefault\":1:{s:4:\"prop\";i:2;}")); +var_dump(unserialize("O:11:\"TestDefault\":2:{s:4:\"prop\";i:2;s:4:\"prop\";i:3;}")); + ?> --EXPECT-- string(30) "O:4:"Test":1:{s:4:"prop";i:1;}" @@ -32,3 +44,20 @@ object(Test)#1 (1) { ["prop"]=> int(3) } +string(38) "O:11:"TestDefault":1:{s:4:"prop";i:1;}" +object(TestDefault)#1 (1) { + ["prop"]=> + int(1) +} +object(TestDefault)#1 (1) { + ["prop"]=> + int(1) +} +object(TestDefault)#1 (1) { + ["prop"]=> + int(2) +} +object(TestDefault)#1 (1) { + ["prop"]=> + int(3) +} diff --git a/Zend/tests/readonly_props/unset.phpt b/Zend/tests/readonly_props/unset.phpt index b8bd4218fa0c..ee86881d288c 100644 --- a/Zend/tests/readonly_props/unset.phpt +++ b/Zend/tests/readonly_props/unset.phpt @@ -54,6 +54,33 @@ try { echo $e->getMessage(), "\n"; } +class Test4 { + public readonly int $prop = 1; + + public function __construct() { + try { + unset($this->prop); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + } + + public function __get($name) { + echo __METHOD__, "\n"; // lazy pattern does not work + $this->prop = 2; + return $this->prop; + } +} + +$test = new Test4; +var_dump($test->prop); // Don't call __get. +try { + unset($test->prop); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +var_dump($test->prop); // Still don't call __get. + ?> --EXPECT-- Cannot unset readonly property Test::$prop @@ -62,3 +89,7 @@ int(1) int(1) Cannot unset readonly property Test2::$prop Cannot unset protected(set) readonly property Test3::$prop from global scope +Cannot unset readonly property Test4::$prop +int(1) +Cannot unset readonly property Test4::$prop +int(1) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ee57e1dafb87..7b190680cfcc 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9240,11 +9240,6 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f zend_error_noreturn(E_COMPILE_ERROR, "Readonly property %s::$%s must have type", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (!Z_ISUNDEF(value_zv)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Readonly property %s::$%s cannot have default value", - ZSTR_VAL(ce->name), ZSTR_VAL(name)); - } if (flags & ZEND_ACC_STATIC) { zend_error_noreturn(E_COMPILE_ERROR, "Static property %s::$%s cannot be readonly", From fe083f3adeb49011f07ebe52de3de09f3543ca48 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Sun, 5 Jul 2026 01:02:07 +0700 Subject: [PATCH 2/3] Added error classes to new test cases --- .../readonly_with_property_default.phpt | 8 ++++---- Zend/tests/readonly_props/readonly_modification.phpt | 4 ++-- Zend/tests/readonly_props/readonly_with_default.phpt | 4 ++-- .../readonly_with_default_asymmetric_visibility.phpt | 10 +++++----- .../readonly_with_default_reflection.phpt | 4 ++-- Zend/tests/readonly_props/unset.phpt | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Zend/tests/readonly_classes/readonly_with_property_default.phpt b/Zend/tests/readonly_classes/readonly_with_property_default.phpt index b6e38e23e8b0..4268ff5734a4 100644 --- a/Zend/tests/readonly_classes/readonly_with_property_default.phpt +++ b/Zend/tests/readonly_classes/readonly_with_property_default.phpt @@ -13,7 +13,7 @@ readonly class Foo try { $this->bar = 2; } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } } } @@ -25,12 +25,12 @@ var_dump($foo->nullable); try { $foo->bar = 3; } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } ?> --EXPECT-- -Cannot modify readonly property Foo::$bar +Error: Cannot modify readonly property Foo::$bar int(1) NULL -Cannot modify readonly property Foo::$bar +Error: Cannot modify readonly property Foo::$bar diff --git a/Zend/tests/readonly_props/readonly_modification.phpt b/Zend/tests/readonly_props/readonly_modification.phpt index 67199cb6ec1a..2e13ad3fb408 100644 --- a/Zend/tests/readonly_props/readonly_modification.phpt +++ b/Zend/tests/readonly_props/readonly_modification.phpt @@ -21,7 +21,7 @@ class TestWithDefault { try { $this->prop = 2; } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } } } @@ -94,5 +94,5 @@ array(0) { } Cannot indirectly modify readonly property Test::$prop2 Cannot indirectly modify readonly property Test::$prop2 -Cannot modify readonly property TestWithDefault::$prop +Error: Cannot modify readonly property TestWithDefault::$prop int(1) diff --git a/Zend/tests/readonly_props/readonly_with_default.phpt b/Zend/tests/readonly_props/readonly_with_default.phpt index 84977bfda1c3..f8e381576e56 100644 --- a/Zend/tests/readonly_props/readonly_with_default.phpt +++ b/Zend/tests/readonly_props/readonly_with_default.phpt @@ -26,7 +26,7 @@ var_dump($test->enumString); try { $test->prop = 2; } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } ?> @@ -42,4 +42,4 @@ array(2) { } enum(E::Case) string(4) "Case" -Cannot modify readonly property Test::$prop +Error: Cannot modify readonly property Test::$prop diff --git a/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt b/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt index 3d31f098f402..a61373edc388 100644 --- a/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt +++ b/Zend/tests/readonly_props/readonly_with_default_asymmetric_visibility.phpt @@ -17,7 +17,7 @@ foreach (['default', 'private', 'protected', 'public'] as $prop) { try { $test->$prop = 42; } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } } @@ -27,7 +27,7 @@ int(1) int(2) int(3) int(4) -Cannot modify readonly property Test::$default -Cannot modify readonly property Test::$private -Cannot modify readonly property Test::$protected -Cannot modify readonly property Test::$public +Error: Cannot modify readonly property Test::$default +Error: Cannot modify readonly property Test::$private +Error: Cannot modify readonly property Test::$protected +Error: Cannot modify readonly property Test::$public diff --git a/Zend/tests/readonly_props/readonly_with_default_reflection.phpt b/Zend/tests/readonly_props/readonly_with_default_reflection.phpt index fd1df1ebff29..b10191b202be 100644 --- a/Zend/tests/readonly_props/readonly_with_default_reflection.phpt +++ b/Zend/tests/readonly_props/readonly_with_default_reflection.phpt @@ -18,7 +18,7 @@ $test = new Foo(); try { $rp->setValue($test, 2); } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } ?> @@ -32,4 +32,4 @@ array(2) { ["nullable"]=> NULL } -Cannot modify readonly property Foo::$prop +Error: Cannot modify readonly property Foo::$prop diff --git a/Zend/tests/readonly_props/unset.phpt b/Zend/tests/readonly_props/unset.phpt index ee86881d288c..f276ecaf2148 100644 --- a/Zend/tests/readonly_props/unset.phpt +++ b/Zend/tests/readonly_props/unset.phpt @@ -61,7 +61,7 @@ class Test4 { try { unset($this->prop); } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } } @@ -77,7 +77,7 @@ var_dump($test->prop); // Don't call __get. try { unset($test->prop); } catch (Error $e) { - echo $e->getMessage(), "\n"; + echo $e::class, ": ", $e->getMessage(), "\n"; } var_dump($test->prop); // Still don't call __get. @@ -89,7 +89,7 @@ int(1) int(1) Cannot unset readonly property Test2::$prop Cannot unset protected(set) readonly property Test3::$prop from global scope -Cannot unset readonly property Test4::$prop +Error: Cannot unset readonly property Test4::$prop int(1) -Cannot unset readonly property Test4::$prop +Error: Cannot unset readonly property Test4::$prop int(1) From 63287bc9d4e81b22b49d40a2909f43d381b3265a Mon Sep 17 00:00:00 2001 From: NickSdot Date: Sun, 5 Jul 2026 11:40:01 +0700 Subject: [PATCH 3/3] Improved tests according to review feedback --- ...adonly_with_default_interface_get_only.phpt} | 14 +------------- ...readonly_with_default_interface_get_set.phpt | 16 ++++++++++++++++ ..._default_interface_get_set_implicit_set.phpt | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 13 deletions(-) rename Zend/tests/readonly_props/{readonly_with_default_interface.phpt => readonly_with_default_interface_get_only.phpt} (51%) create mode 100644 Zend/tests/readonly_props/readonly_with_default_interface_get_set.phpt create mode 100644 Zend/tests/readonly_props/readonly_with_default_interface_get_set_implicit_set.phpt diff --git a/Zend/tests/readonly_props/readonly_with_default_interface.phpt b/Zend/tests/readonly_props/readonly_with_default_interface_get_only.phpt similarity index 51% rename from Zend/tests/readonly_props/readonly_with_default_interface.phpt rename to Zend/tests/readonly_props/readonly_with_default_interface_get_only.phpt index a20d869dc661..2a17204255fe 100644 --- a/Zend/tests/readonly_props/readonly_with_default_interface.phpt +++ b/Zend/tests/readonly_props/readonly_with_default_interface_get_only.phpt @@ -12,18 +12,6 @@ class C implements I { } var_dump(new C()->prop); - -interface J { - public int $prop { get; set; } -} - -// does not satisfy set -class D implements J { - public readonly int $prop = 42; -} - ?> --EXPECTF-- -int(42) - -Fatal error: Set access level of D::$prop must be omitted (as in class J) in %s on line %d +int(42) \ No newline at end of file diff --git a/Zend/tests/readonly_props/readonly_with_default_interface_get_set.phpt b/Zend/tests/readonly_props/readonly_with_default_interface_get_set.phpt new file mode 100644 index 000000000000..102444cc044f --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_interface_get_set.phpt @@ -0,0 +1,16 @@ +--TEST-- +Readonly public(set) property with default value does not satisfy get/set interface property +--FILE-- + +--EXPECTF-- +Fatal error: Class C contains 1 abstract method and must therefore be declared abstract or implement the remaining method (I::$prop::set) in %s on line %d diff --git a/Zend/tests/readonly_props/readonly_with_default_interface_get_set_implicit_set.phpt b/Zend/tests/readonly_props/readonly_with_default_interface_get_set_implicit_set.phpt new file mode 100644 index 000000000000..106bf2aeb0cf --- /dev/null +++ b/Zend/tests/readonly_props/readonly_with_default_interface_get_set_implicit_set.phpt @@ -0,0 +1,17 @@ +--TEST-- +Readonly property with default value has restricted set visibility for get/set interface property +--DESCRIPTION-- +The error message should be improved, the set access level comes from readonly. Ref: Zend/tests/property_hooks/interface_get_set_readonly.phpt +--FILE-- + +--EXPECTF-- +Fatal error: Set access level of C::$prop must be omitted (as in class I) in %s on line %d