Skip to content

Commit fff5771

Browse files
committed
Require non-absolute trait method refs to be unambiguous
Currently, when writing something like class X { use T1, T2 { func as otherFunc; } function func() {} } where both T1::func() and T2::func() exist, we will simply assume that func refers to T1::func(). This is surprising, and it doesn't really make sense that this particular method gets picked. This commit validates that non-absolute method references are unambiguous, i.e. refer to exactly one method. If there is ambiguity, it is required to write T1::func as otherFunc or similar. Closes GH-5232.
1 parent d2b902f commit fff5771

File tree

5 files changed

+88
-3
lines changed

5 files changed

+88
-3
lines changed

UPGRADING

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,20 @@ PHP 8.0 UPGRADE NOTES
149149

150150
function test($a = [], $b) {} // Deprecated
151151
function test(Foo $a = null, $b) {} // Allowed
152+
. Non-absolute trait method references in trait alias adaptations are now
153+
required to be unambiguous:
154+
155+
class X {
156+
use T1, T2 {
157+
func as otherFunc;
158+
}
159+
function func() {}
160+
}
161+
162+
If both T1::func() and T2::func() exist, this code was previously silently
163+
accepted, and func as assumed to refer to T1::func. Now it will generate a
164+
fatal error instead, and either T1::func or T2::func needs to be written
165+
explicitly.
152166

153167
- COM:
154168
. Removed the ability to import case-insensitive constants from type

Zend/tests/bug62069.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Bug #62069: binding wrong traits if they have same name methods
3+
--FILE--
4+
<?php
5+
6+
trait T1 {
7+
public function func() {
8+
echo "From T1\n";
9+
}
10+
}
11+
12+
trait T2 {
13+
public function func() {
14+
echo "From T2\n";
15+
}
16+
}
17+
18+
class Bar {
19+
public function func() {
20+
echo "From Bar\n";
21+
}
22+
use T1, T2 {
23+
func as f1;
24+
}
25+
}
26+
27+
$b = new Bar();
28+
$b->f2();
29+
30+
?>
31+
--EXPECTF--
32+
Fatal error: An alias was defined for method func(), which exists in both T1 and T2. Use T1::func or T2::func to resolve the ambiguity in %s on line %d

Zend/tests/bug62069_2.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Bug #62069: binding wrong traits if they have same name methods (variation 2)
3+
--FILE--
4+
<?php
5+
6+
trait T1 {
7+
public function func() {
8+
echo "From T1\n";
9+
}
10+
}
11+
12+
trait T2 {
13+
public function func() {
14+
echo "From T2\n";
15+
}
16+
}
17+
18+
class Bar {
19+
public function func() {
20+
echo "From Bar\n";
21+
}
22+
use T1 {
23+
func as f1;
24+
}
25+
use T2 {
26+
func as f2;
27+
}
28+
}
29+
30+
$b = new Bar();
31+
$b->f2();
32+
33+
?>
34+
--EXPECTF--
35+
Fatal error: An alias was defined for method func(), which exists in both T1 and T2. Use T1::func or T2::func to resolve the ambiguity in %s on line %d

Zend/tests/traits/language011.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ trait World {
1818

1919

2020
class MyClass {
21-
use Hello, World { sayHello as sayWorld; }
21+
use Hello, World { World::sayHello as sayWorld; }
2222
}
2323

2424
$o = new MyClass();

Zend/zend_inheritance.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,8 +1858,12 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
18581858
continue;
18591859
}
18601860

1861-
// TODO: This is ambiguous! The first trait is assumed.
1862-
break;
1861+
zend_error_noreturn(E_COMPILE_ERROR,
1862+
"An alias was defined for method %s(), which exists in both %s and %s. Use %s::%s or %s::%s to resolve the ambiguity",
1863+
ZSTR_VAL(cur_method_ref->method_name),
1864+
ZSTR_VAL(trait->name), ZSTR_VAL(traits[j]->name),
1865+
ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name),
1866+
ZSTR_VAL(traits[j]->name), ZSTR_VAL(cur_method_ref->method_name));
18631867
}
18641868
}
18651869
}

0 commit comments

Comments
 (0)