From d54268fd8d56be75db7216bc188b5741d000c43d Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Sat, 11 Jul 2026 13:11:03 +0800 Subject: [PATCH] refactor(aot): update object extension method lookup logic - Modified findObjectExtensionMethod to clarify that static lookup is only used for named MethodCall AST paths - Added distinction between static method name resolution and dynamic method calls - Updated documentation to explain that real methods are resolved before extension fallback - Clarified that __call() magic method is only used when no valid extension exists - Added test coverage for missing method calls using __call magic method - Included dynamic method name handling in test assertions --- src/UniversalMethodCall.php | 8 +++++--- tests/aot/universal_method/object_extension.phpt | 12 ++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/UniversalMethodCall.php b/src/UniversalMethodCall.php index c30c19ba..2f629edc 100644 --- a/src/UniversalMethodCall.php +++ b/src/UniversalMethodCall.php @@ -413,9 +413,11 @@ trait UniversalMethodCall } /** - * Look up an object extension in the object's own namespace. Functions use - * {Class}_{snake_case_method} or {Class}_{lowerCamelCaseMethod}, and their - * first parameter must be exactly the extended class. + * Look up a statically compiled object extension in the object's own + * namespace. This lookup is only used by the named MethodCall AST path; + * dynamic method names and StaticCall nodes deliberately do not use it. + * Real methods are resolved before this fallback, while __call() is used + * only if no valid extension exists. */ protected function findObjectExtensionMethod(string $class, string $method): ?array { diff --git a/tests/aot/universal_method/object_extension.phpt b/tests/aot/universal_method/object_extension.phpt index bd5fdd7a..5cbc5cf0 100644 --- a/tests/aot/universal_method/object_extension.phpt +++ b/tests/aot/universal_method/object_extension.phpt @@ -16,6 +16,11 @@ namespace App { { return 'real method'; } + + public function __call(string $method, array $args): string + { + return 'magic:' . $method; + } } function User_test_method(User $user, string $suffix): string @@ -54,6 +59,11 @@ namespace { var_dump($user->formatName()); var_dump($user->existing()); var_dump((new \App\User('bob'))->displayName()); + var_dump($user->missingMethod()); + + // Dynamic method names do not participate in static extension lookup. + $dynamicMethod = 'displayName'; + var_dump($user->$dynamicMethod()); } } ?> @@ -63,3 +73,5 @@ string(11) "ALICE:camel" string(7) "[alice]" string(11) "real method" string(9) "BOB:camel" +string(19) "magic:missingMethod" +string(17) "magic:displayName"