Skip to content

Commit e3cee1b

Browse files
GH-17860: allow final in constructor property promotion
1 parent 352aca1 commit e3cee1b

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ PHP NEWS
1717
`__callStatic` is allowed). (timwolla)
1818
. Fixed bug GH-17713 (ReflectionProperty::getRawValue() and related methods
1919
may call hooks of overridden properties). (Arnaud)
20+
. Fixed bug GH-17860 (Final properties cannot use constructor property
21+
promotion). (DanielEScherzer)
2022

2123
- DOM:
2224
. Fixed bug GH-17609 (Typo in error message: Dom\NO_DEFAULT_NS instead of
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Promoted property may be marked final (hook)
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public function __construct(
8+
public final $prop { get {} set {} }
9+
) {}
10+
}
11+
12+
class B extends A {
13+
public $prop { get {} set {} }
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Cannot override final property A::$prop in %s on line %d
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Promoted property may be marked final (normal)
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public function __construct(
8+
public final $prop
9+
) {}
10+
}
11+
12+
class B extends A {
13+
public $prop { get {} set {} }
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Cannot override final property A::$prop in %s on line %d
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Confirm that the AST indicates final promoted properties
3+
--FILE--
4+
<?php
5+
try {
6+
assert(false && new class {
7+
public function __construct( public final $prop ) {}
8+
});
9+
} catch (Error $e) {
10+
echo $e->getMessage(), "\n";
11+
}
12+
?>
13+
--EXPECT--
14+
assert(false && new class {
15+
public function __construct(public final $prop) {
16+
}
17+
18+
})

Zend/zend_ast.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,6 +2555,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
25552555
zend_ast_export_attributes(str, ast->child[3], indent, 0);
25562556
}
25572557
zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CPP);
2558+
if (ast->attr & ZEND_ACC_FINAL) {
2559+
smart_str_appends(str, "final ");
2560+
}
25582561
if (ast->child[0]) {
25592562
zend_ast_export_type(str, ast->child[0], indent);
25602563
smart_str_appendc(str, ' ');

Zend/zend_compile.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -899,13 +899,7 @@ uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token
899899
}
900900
break;
901901
case T_FINAL:
902-
if (target == ZEND_MODIFIER_TARGET_METHOD
903-
|| target == ZEND_MODIFIER_TARGET_CONSTANT
904-
|| target == ZEND_MODIFIER_TARGET_PROPERTY
905-
|| target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
906-
return ZEND_ACC_FINAL;
907-
}
908-
break;
902+
return ZEND_ACC_FINAL;
909903
case T_STATIC:
910904
if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_METHOD) {
911905
return ZEND_ACC_STATIC;
@@ -7598,7 +7592,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
75987592
zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
75997593
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
76007594
bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7601-
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
7595+
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL);
76027596
bool is_promoted = property_flags || hooks_ast;
76037597

76047598
znode var_node, default_node;

0 commit comments

Comments
 (0)