Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ PHP 8.5 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/attributes-on-constants
. Added the pipe (|>) operator.
RFC: https://wiki.php.net/rfc/pipe-operator-v3
. Constructor property promotion can now be used for final properties.
RFC: https://wiki.php.net/rfc/final_promotion

- Curl:
. Added support for share handles that are persisted across multiple PHP
Expand Down
18 changes: 18 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Promoted property may be marked final (hook)
--FILE--
<?php

class A {
public function __construct(
public final $prop { get {} set {} }
) {}
}

class B extends A {
public $prop { get {} set {} }
}

?>
--EXPECTF--
Fatal error: Cannot override final property A::$prop in %s on line %d
18 changes: 18 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Promoted property may be marked final (normal)
--FILE--
<?php

class A {
public function __construct(
public final $prop
) {}
}

class B extends A {
public $prop { get {} set {} }
}

?>
--EXPECTF--
Fatal error: Cannot override final property A::$prop in %s on line %d
18 changes: 18 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Promoted property may be marked final (no visibility needed)
--FILE--
<?php

class A {
public function __construct(
final $prop
) {}
}

class B extends A {
public $prop { get {} set {} }
}

?>
--EXPECTF--
Fatal error: Cannot override final property A::$prop in %s on line %d
18 changes: 18 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_4.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Final promoted property conflicts with non-promoted non-hooked property
--FILE--
<?php

class A {
public function __construct(
final $prop
) {}
}

class B extends A {
public $prop;
}

?>
--EXPECTF--
Fatal error: Cannot override final property A::$prop in %s on line %d
28 changes: 28 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_5.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
Non-promoted constructor parameter does not conflict with final promoted property
--FILE--
<?php

class A {
public function __construct(
final $prop
) {
echo __METHOD__ . "(): $prop\n";
}
}

class B extends A {
public function __construct(
$prop
) {
echo __METHOD__ . "(): $prop\n";
parent::__construct($prop);
}
}

$b = new B("test" );

?>
--EXPECT--
B::__construct(): test
A::__construct(): test
18 changes: 18 additions & 0 deletions Zend/tests/property_hooks/final_prop_promoted_ast.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Confirm that the AST indicates final promoted properties
--FILE--
<?php
try {
assert(false && new class {
public function __construct( public final $prop ) {}
});
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
assert(false && new class {
public function __construct(public final $prop) {
}

})
3 changes: 3 additions & 0 deletions Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -2795,6 +2795,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_FINAL) {
smart_str_appends(str, "final ");
}
if (ast->child[0]) {
zend_ast_export_type(str, ast->child[0], indent);
smart_str_appendc(str, ' ');
Expand Down
10 changes: 2 additions & 8 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,13 +903,7 @@ uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token
}
break;
case T_FINAL:
if (target == ZEND_MODIFIER_TARGET_METHOD
|| target == ZEND_MODIFIER_TARGET_CONSTANT
|| target == ZEND_MODIFIER_TARGET_PROPERTY
|| target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
return ZEND_ACC_FINAL;
}
break;
return ZEND_ACC_FINAL;
case T_STATIC:
if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_METHOD) {
return ZEND_ACC_STATIC;
Expand Down Expand Up @@ -7681,7 +7675,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL);
bool is_promoted = property_flags || hooks_ast;

znode var_node, default_node;
Expand Down
4 changes: 4 additions & 0 deletions ext/reflection/tests/ReflectionProperty_isFinal.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class C {
public protected(set) final mixed $p6;
public private(set) mixed $p7;
public private(set) final mixed $p8;

public function __construct( final $p9, public $p10 ) {}
}

$rc = new ReflectionClass(C::class);
Expand All @@ -30,3 +32,5 @@ p5: bool(false)
p6: bool(true)
p7: bool(true)
p8: bool(true)
p9: bool(true)
p10: bool(false)
Loading