Skip to content

fix(compiler): preserve runtime class dispatch and introspection for polymorphic objects - #110

Open
prateekbhujel wants to merge 1 commit into
swoole:masterfrom
prateekbhujel:prateek/preserve-runtime-class-dispatch
Open

fix(compiler): preserve runtime class dispatch and introspection for polymorphic objects#110
prateekbhujel wants to merge 1 commit into
swoole:masterfrom
prateekbhujel:prateek/preserve-runtime-class-dispatch

Conversation

@prateekbhujel

@prateekbhujel prateekbhujel commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

When an object comes from a function or method return (like $a = getAnimal()), SSA marks it in stableObjects. But that only tracks the upper-bound declared type, not the actual runtime subclass:

  • get_class($a) was getting folded at compile time to the base class instead of returning the runtime subclass (and returned a string on null instead of throwing TypeError)
  • $a::who() statically resolved to the base class, bypassing subclass overrides

Swapped isStableObject with isset($this->context->exactObjects[...]) in genGetClassOptimized and parseStaticCall. If the class isn't proven exact via new ConcreteClass(), it safely falls back to runtime dispatch (php::fn::get_class and php::callStaticMethod).

Added unit tests for both exact and polymorphic cases.

…polymorphic objects

When an object variable has an upper-bound declared type (e.g. assigned from
a function or method return), SSA marks it as a stable object. However,
stableObjects does not guarantee the concrete runtime class: the instance
may be a subclass at runtime, or null if nullable.

1. FuncCallOptimizer::genGetClassOptimized checked isStableObject($obj->name)
   and folded get_class($obj) to the declared type literal string. For
   $a = getAnimal() returning a Dog, get_class($a) was incorrectly folded
   to "Animal" at compile time.
2. MethodCallTrait::parseStaticCall checked isStableObject($class) and
   jumped to _do_call with the declared base class. For $a::who(), this
   statically invoked Base::who() instead of dispatching to Dog::who() on
   the runtime object.

Require proven exact object instances (exactObjects, populated from direct
new ConcreteClass() definitions) before folding get_class() or devirtualizing
static calls on object variables. Non-exact variables fall back to runtime
class resolution (php::fn::get_class() and php::callStaticMethod()),
matching PHP semantics.

Add unit test coverage verifying exact objects continue to fold/devirtualize
while polymorphic variables retain dynamic runtime dispatch.
@prateekbhujel
prateekbhujel force-pushed the prateek/preserve-runtime-class-dispatch branch from e1e645c to 2a8f442 Compare September 12, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant