From 1476e5a4ebcd7a6befec7f23a65156699924b8af Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 26 May 2026 20:15:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(universal-method):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95=E9=93=BE=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B=E6=8E=A8?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在内置方法查找后添加扩展方法的返回类型检查 - 重构 findExtensionMethod 调用逻辑以支持链式调用场景 - 使用函数定义的返回类型而非默认的 TYPE_VAR - 移除冗余的命名空间函数查找逻辑 --- src/Php/UniversalMethodCall.php | 21 ++++--- .../aot/universal_method_extension_chain.phpt | 55 +++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 tests/aot/universal_method_extension_chain.phpt diff --git a/src/Php/UniversalMethodCall.php b/src/Php/UniversalMethodCall.php index 6728a44a..8850a115 100644 --- a/src/Php/UniversalMethodCall.php +++ b/src/Php/UniversalMethodCall.php @@ -340,10 +340,19 @@ trait UniversalMethodCall if ($def !== null) { return $def['return_type']; } + $ext = $this->findExtensionMethod($searchType, $method); + if ($ext !== null) { + return $ext['return_type']; + } } return null; } - return static::UNIVERSAL_METHODS[$type][$method]['return_type'] ?? null; + $builtin = static::UNIVERSAL_METHODS[$type][$method]['return_type'] ?? null; + if ($builtin !== null) { + return $builtin; + } + $ext = $this->findExtensionMethod($type, $method); + return $ext ? $ext['return_type'] : null; } private const array TYPE_EXTENSION_PREFIX = [ @@ -407,11 +416,13 @@ trait UniversalMethodCall return null; } + $funcDef = $this->getFunction($funcName); + return [ 'handler' => 'php_fn', 'fn' => $funcName, 'receiver_pos' => 1, - 'return_type' => self::TYPE_VAR, + 'return_type' => $funcDef->returnType, 'min_args' => 0, 'max_args' => -1, ]; @@ -422,12 +433,6 @@ trait UniversalMethodCall if ($this->hasFunction($funcName)) { return $funcName; } - if ($this->namespace) { - $nsFunc = $this->namespace . '\\' . $funcName; - if ($this->hasFunction($nsFunc)) { - return $nsFunc; - } - } return null; } diff --git a/tests/aot/universal_method_extension_chain.phpt b/tests/aot/universal_method_extension_chain.phpt new file mode 100644 index 00000000..cc956478 --- /dev/null +++ b/tests/aot/universal_method_extension_chain.phpt @@ -0,0 +1,55 @@ +--TEST-- +Universal method: extension function chaining with typed return +--FILE-- + 'one', 2 => 'two', 3 => 'three']; + return $map[$int] ?? 'unknown'; +} + +function str_double(string $str): string +{ + return $str . $str; +} + +function str_get_length(string $str): int +{ + return strlen($str); +} + +function str_to_array(string $str, string $delimiter): array +{ + return $str->split($delimiter); +} + +function array_last(array $arr): mixed { + if ($arr->count() === 0) { + return null; + } + return $arr[$arr->count() - 1]; +} + +function main() +{ + $num = 2; + var_dump($num->toWords()->upper()); + var_dump($num->toWords()->double()->upper()); + + $str = "hello"; + var_dump($str->getLength()->add(100)); + var_dump($str->double()->length()); + + $str2 = "hello world"; + var_dump($str2->split(" ")->last()); +} +?> +--EXPECT-- +string(3) "TWO" +string(6) "TWOTWO" +int(105) +int(10) +string(5) "world" \ No newline at end of file