You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
#[Override] attribute in trait does not check for parent class implementations #12189
When adding the #[Override] attribute to a trait method, then use-ing it in a class, a runtime error is triggered even if a parent class defines a matching method. This does not happen when an interface with matching signature is encountered.
The following excerpt from the rfc made me expect this would work:
Methods from a used trait behave as if the method definition was copied and pasted into the target class. Specifically the #[\Override] attribute on a trait method requires the existence of a matching method in a parent class or implemented interface.
The following code:
<?phpclass A {
publicfunctionfoo(): void {}
}
interface I {
publicfunctionfoo(): void;
}
trait T {
#[\Override]
publicfunctionfoo(): void {
echo'foo';
}
}
// Works fineclass B implements I {
use T;
}
// Works fine ("copied and pasted into the target class")class C extends A {
#[\Override]
publicfunctionfoo(): void {
echo'foo';
}
}
// Does not workclass D extends A {
use T;
}
Resulted in this output:
PHP Fatal error: D::foo() has #[\Override] attribute, but no matching parent method exists in mwe.php on line 13
PHP Stack trace:
PHP 1. {main}() mwe.php:0
Fatal error: D::foo() has #[\Override] attribute, but no matching parent method exists in mwe.php on line 13
Call Stack:
0.0002 364504 1. {main}() mwe.php:0
if (!check_only&&child->common.scope==ce) {
child->common.fn_flags &= ~ZEND_ACC_OVERRIDE;
}
The second condition doesn't trigger because the method doesn't belong to the class, it belongs to the trait. However, getting rid of the condition is a bad idea because it may load to modification inside shm as the trait is shared.
And duplicating the function seems like a very ugly solution.
Activity
ndossche commentedon Sep 12, 2023
Seems to be because of the flag removal code:
The second condition doesn't trigger because the method doesn't belong to the class, it belongs to the trait. However, getting rid of the condition is a bad idea because it may load to modification inside shm as the trait is shared.
And duplicating the function seems like a very ugly solution.
TimWolla commentedon Sep 12, 2023
Without looking yet into this again (I fear it's above my pay-grade based on your description), I wonder why it works fine for interfaces then 🤔
Looking at the tests, it appears this issue found the only case that is not covered by the tests 😔
Fix #[Override] on traits overriding a parent method without a matchi…
Merge branch 'PHP-8.3' into phpgh-12189
Fix #[Override] on traits overriding a parent method without a matchi…
jnoordsij commentedon Sep 15, 2023
@TimWolla thanks for fixing!
TimWolla commentedon Sep 15, 2023
@jnoordsij Thank you for testing the release candidates and also for finding the bug 😃