From fff5771cccaca49565c90349320f3c06cbe19328 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 3 Mar 2020 14:31:09 +0100 Subject: [PATCH] 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. --- UPGRADING | 14 ++++++++++++ Zend/tests/bug62069.phpt | 32 +++++++++++++++++++++++++++ Zend/tests/bug62069_2.phpt | 35 ++++++++++++++++++++++++++++++ Zend/tests/traits/language011.phpt | 2 +- Zend/zend_inheritance.c | 8 +++++-- 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/bug62069.phpt create mode 100644 Zend/tests/bug62069_2.phpt 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-- +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-- +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)); } } } -- 2.40.0