Skip to content

Commit 077c940

Browse files
committed
refactor: addressed #18757 (comment)
1 parent 324e61e commit 077c940

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Backed readonly property with hooks in abstract class
3+
--FILE--
4+
<?php
5+
abstract class Test {
6+
7+
public readonly int $prop {
8+
get => $this->prop;
9+
set => $value;
10+
}
11+
12+
public function __construct(int $v) {
13+
$this->prop = $v;
14+
}
15+
16+
public function set(int $v) {
17+
$this->prop = $v;
18+
}
19+
}
20+
21+
class Child extends Test {}
22+
23+
$ch = new Child(42);
24+
var_dump($ch->prop);
25+
try {
26+
$ch->set(43);
27+
} catch (Error $e) {
28+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
29+
}
30+
try {
31+
$ch->prop = 43;
32+
} catch (Error $e) {
33+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
34+
}
35+
var_dump($ch->prop);
36+
?>
37+
--EXPECT--
38+
int(42)
39+
Error: Cannot modify readonly property Test::$prop
40+
Error: Cannot modify protected(set) readonly property Test::$prop from global scope
41+
int(42)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Hooked properties in abstract classes cannot be readonly
2+
Virtual readonly property in abstract class triggers non-abstract body error
33
--FILE--
44
<?php
55

@@ -8,4 +8,4 @@ abstract class Test {
88
}
99
?>
1010
--EXPECTF--
11-
Fatal error: Hooked properties in abstract classes cannot be declared readonly in %s on line %d
11+
Fatal error: Non-abstract property hook must have a body in %s on line %d
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Property hook cannot be both abstract and readonly
3+
--FILE--
4+
<?php
5+
abstract class Test {
6+
abstract public readonly int $prop { get; }
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Abstract hooked properties cannot be declared readonly in %s on line %d

Zend/zend_compile.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8497,20 +8497,6 @@ static void zend_compile_property_hooks(
84978497
{
84988498
zend_class_entry *ce = CG(active_class_entry);
84998499

8500-
/* Allow hooks on backed readonly properties only. */
8501-
if ((prop_info->flags & (ZEND_ACC_READONLY|ZEND_ACC_VIRTUAL)) == (ZEND_ACC_READONLY|ZEND_ACC_VIRTUAL)) {
8502-
8503-
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8504-
zend_error_noreturn(E_COMPILE_ERROR, "Interface properties cannot be declared readonly");
8505-
}
8506-
8507-
if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
8508-
zend_error_noreturn(E_COMPILE_ERROR, "Hooked properties in abstract classes cannot be declared readonly");
8509-
}
8510-
8511-
zend_error_noreturn(E_COMPILE_ERROR, "Hooked virtual properties cannot be declared readonly");
8512-
}
8513-
85148500
if (hooks->children == 0) {
85158501
zend_error_noreturn(E_COMPILE_ERROR, "Property hook list must not be empty");
85168502
}
@@ -8666,6 +8652,20 @@ static void zend_compile_property_hooks(
86668652
}
86678653
}
86688654

8655+
/* Allow hooks on backed readonly properties only. */
8656+
if ((prop_info->flags & (ZEND_ACC_READONLY|ZEND_ACC_VIRTUAL)) == (ZEND_ACC_READONLY|ZEND_ACC_VIRTUAL)) {
8657+
8658+
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
8659+
zend_error_noreturn(E_COMPILE_ERROR, "Interface properties cannot be declared readonly");
8660+
}
8661+
8662+
if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
8663+
zend_error_noreturn(E_COMPILE_ERROR, "Abstract hooked properties cannot be declared readonly");
8664+
}
8665+
8666+
zend_error_noreturn(E_COMPILE_ERROR, "Hooked virtual properties cannot be declared readonly");
8667+
}
8668+
86698669
ce->num_hooked_props++;
86708670

86718671
/* See zend_link_hooked_object_iter(). */

0 commit comments

Comments
 (0)