Skip to content

Commit 28a6372

Browse files
committed
Fix prototype for trait methods
Fixes GH-14009
1 parent b3e26c3 commit 28a6372

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

Zend/tests/gh14009.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
GH-14009: Traits inherit prototype
3+
--FILE--
4+
<?php
5+
6+
class P {
7+
protected function common() {
8+
throw new Exception('Unreachable');
9+
}
10+
}
11+
12+
class A extends P {
13+
public function test(P $sibling) {
14+
$sibling->common();
15+
}
16+
}
17+
18+
class B extends P {
19+
protected function common() {
20+
echo __METHOD__, "\n";
21+
}
22+
}
23+
24+
trait T {
25+
protected function common() {
26+
echo __METHOD__, "\n";
27+
}
28+
}
29+
30+
class C extends P {
31+
use T;
32+
}
33+
34+
$a = new A();
35+
$a->test(new B());
36+
$a->test(new C());
37+
38+
?>
39+
--EXPECT--
40+
B::common
41+
T::common

Zend/zend_inheritance.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,20 +1146,24 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
11461146
parent = proto;
11471147
}
11481148

1149-
if (!check_only && child->common.prototype != proto && child_zv) {
1149+
if (!check_only && child->common.prototype != proto) {
11501150
do {
1151+
bool copied = false;
11511152
if (child->common.scope != ce && child->type == ZEND_USER_FUNCTION) {
11521153
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
11531154
/* Few parent interfaces contain the same method */
11541155
break;
1155-
} else {
1156+
} else if (child_zv) {
11561157
/* op_array wasn't duplicated yet */
11571158
zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
11581159
memcpy(new_function, child, sizeof(zend_op_array));
11591160
Z_PTR_P(child_zv) = child = new_function;
1161+
copied = true;
11601162
}
11611163
}
1162-
child->common.prototype = proto;
1164+
if (copied || child_scope == ce) {
1165+
child->common.prototype = proto;
1166+
}
11631167
} while (0);
11641168
}
11651169

0 commit comments

Comments
 (0)