summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-03-03 14:31:09 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-03-10 16:01:13 +0100
commitfff5771cccaca49565c90349320f3c06cbe19328 (patch)
tree9e47e32c4f3f1da0211b5243fa9f0a503fd71090
parentd2b902f174b2e8c98bf5d4e257924a96b1323776 (diff)
downloadphp-git-fff5771cccaca49565c90349320f3c06cbe19328.tar.gz
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.
-rw-r--r--UPGRADING14
-rw-r--r--Zend/tests/bug62069.phpt32
-rw-r--r--Zend/tests/bug62069_2.phpt35
-rw-r--r--Zend/tests/traits/language011.phpt2
-rw-r--r--Zend/zend_inheritance.c8
5 files changed, 88 insertions, 3 deletions
diff --git a/UPGRADING b/UPGRADING
index 41a72c280d..db8e2eb22e 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -149,6 +149,20 @@ PHP 8.0 UPGRADE NOTES
function test($a = [], $b) {} // Deprecated
function test(Foo $a = null, $b) {} // Allowed
+ . Non-absolute trait method references in trait alias adaptations are now
+ required to be unambiguous:
+
+ class X {
+ use T1, T2 {
+ func as otherFunc;
+ }
+ function func() {}
+ }
+
+ If both T1::func() and T2::func() exist, this code was previously silently
+ accepted, and func as assumed to refer to T1::func. Now it will generate a
+ fatal error instead, and either T1::func or T2::func needs to be written
+ explicitly.
- COM:
. Removed the ability to import case-insensitive constants from type
diff --git a/Zend/tests/bug62069.phpt b/Zend/tests/bug62069.phpt
new file mode 100644
index 0000000000..d434e271c6
--- /dev/null
+++ b/Zend/tests/bug62069.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #62069: binding wrong traits if they have same name methods
+--FILE--
+<?php
+
+trait T1 {
+ public function func() {
+ echo "From T1\n";
+ }
+}
+
+trait T2 {
+ public function func() {
+ echo "From T2\n";
+ }
+}
+
+class Bar {
+ public function func() {
+ echo "From Bar\n";
+ }
+ use T1, T2 {
+ func as f1;
+ }
+}
+
+$b = new Bar();
+$b->f2();
+
+?>
+--EXPECTF--
+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
diff --git a/Zend/tests/bug62069_2.phpt b/Zend/tests/bug62069_2.phpt
new file mode 100644
index 0000000000..c7c42ba6d1
--- /dev/null
+++ b/Zend/tests/bug62069_2.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #62069: binding wrong traits if they have same name methods (variation 2)
+--FILE--
+<?php
+
+trait T1 {
+ public function func() {
+ echo "From T1\n";
+ }
+}
+
+trait T2 {
+ public function func() {
+ echo "From T2\n";
+ }
+}
+
+class Bar {
+ public function func() {
+ echo "From Bar\n";
+ }
+ use T1 {
+ func as f1;
+ }
+ use T2 {
+ func as f2;
+ }
+}
+
+$b = new Bar();
+$b->f2();
+
+?>
+--EXPECTF--
+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
diff --git a/Zend/tests/traits/language011.phpt b/Zend/tests/traits/language011.phpt
index 44de874705..1f5b496308 100644
--- a/Zend/tests/traits/language011.phpt
+++ b/Zend/tests/traits/language011.phpt
@@ -18,7 +18,7 @@ trait World {
class MyClass {
- use Hello, World { sayHello as sayWorld; }
+ use Hello, World { World::sayHello as sayWorld; }
}
$o = new MyClass();
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index a031207b85..eab275e509 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -1858,8 +1858,12 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
continue;
}
- // TODO: This is ambiguous! The first trait is assumed.
- break;
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "An alias was defined for method %s(), which exists in both %s and %s. Use %s::%s or %s::%s to resolve the ambiguity",
+ ZSTR_VAL(cur_method_ref->method_name),
+ ZSTR_VAL(trait->name), ZSTR_VAL(traits[j]->name),
+ ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name),
+ ZSTR_VAL(traits[j]->name), ZSTR_VAL(cur_method_ref->method_name));
}
}
}