Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 8.4: dynamic dispatch problem with traits and inheritance #18174

Open
procodix opened this issue Mar 28, 2025 · 5 comments
Open

PHP 8.4: dynamic dispatch problem with traits and inheritance #18174

procodix opened this issue Mar 28, 2025 · 5 comments

Comments

@procodix
Copy link

procodix commented Mar 28, 2025

Description

I have the following bug. I think it might by a corner case. It is very hard to narrow down. Please find this reduces example. In my real code many more traits are involved, as are promoted properties, property hooks, etc. I cannot pinpoint the error to a specific version, but Im sure, it worked correctly in PHP 8.3.

trait X {
    public function test() {echo 'this is from A';}
}

class A {
    use X;
}

class B extends A {
    public function test() {echo 'this is from B';}
}

class C extends B {
	public function run() {
		$this->test(); // this outputs 'this is from A' !!! 
	}
	
	// however if I include this function, it works correctly by echoing 'this is from B'
	// public function test() {
	// 	parent::test();
	// }

	// whats even more weird, is that an almost identical class D works correctly
}

So the call to C->test() skips the inherited B->test() and dispatches to A/X->test().

I ruled out, that

  • a rouge "test" function exists, that takes over
  • visibility problems with public
  • a wrong class is used because of a namespace inaccuracy

Most interesting is, that the pure existence of the called method in C with an explicit call to the parent clears the issue. As this should be redundant, I assume a bug.

Please let me know, if I should provide more details. As it is very difficult to reduce the code to a non-working example, thought, maybe something changed in PHP 8.4 regarding dynamic dispatch which could lead to this behavior.

PHP Version

PHP 8.4

Operating System

macOS 15

@TimWolla
Copy link
Member

I'm unable to reproduce the issue on https://3v4l.org/ejRtn.

Is the issue reliably appearing for you with the example script or is it happening randomly?

@procodix
Copy link
Author

procodix commented Mar 28, 2025

Thanks for the fast reply. The code is just a very condensed example, that abstracts the structure/problem. As soon as as I introduce the method in the class C it works. Removing it results in the erroneous call.

@nielsdos
Copy link
Member

Do you have a reproducer or can you share the code where it happens in?
Also please answer the following questions:

  • What is the exact PHP 8.4 version number that you use, there have been multiple 8.4 releases so far
  • Does this happen with opcache on/off or both?
  • Is the JIT involved?

@procodix
Copy link
Author

procodix commented Mar 28, 2025

PHP 8.4.5

  • Opcode Caching | Up and Running
  • Optimization | Enabled
  • SHM Cache | Enabled
  • File Cache | Disabled
  • JIT | Disabled

I only noticed this in the code I'm currently working on. It's not public, so sharing is not possible. But I could offer a screen sharing.

@iluuu1994
Copy link
Member

It's going to be very challenging to help you if we don't have a reliable reproducer. There's also a patch for master that should be merged soon which changes the order in which traits are bound, to hopefully make some trait edge cases less surprising. #15878 Possibly, this will help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants