diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-03-03 14:31:09 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-03-10 16:01:13 +0100 |
commit | fff5771cccaca49565c90349320f3c06cbe19328 (patch) | |
tree | 9e47e32c4f3f1da0211b5243fa9f0a503fd71090 | |
parent | d2b902f174b2e8c98bf5d4e257924a96b1323776 (diff) | |
download | php-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-- | UPGRADING | 14 | ||||
-rw-r--r-- | Zend/tests/bug62069.phpt | 32 | ||||
-rw-r--r-- | Zend/tests/bug62069_2.phpt | 35 | ||||
-rw-r--r-- | Zend/tests/traits/language011.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_inheritance.c | 8 |
5 files changed, 88 insertions, 3 deletions
@@ -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)); } } } |