fix(universal-method): 修复扩展方法链式调用的返回类型推断

- 在内置方法查找后添加扩展方法的返回类型检查
- 重构 findExtensionMethod 调用逻辑以支持链式调用场景
- 使用函数定义的返回类型而非默认的 TYPE_VAR
- 移除冗余的命名空间函数查找逻辑
pull/1/head
韩天峰 3 months ago
parent eb31e3584b
commit 1476e5a4eb
  1. 21
      src/Php/UniversalMethodCall.php
  2. 55
      tests/aot/universal_method_extension_chain.phpt

@ -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;
}

@ -0,0 +1,55 @@
--TEST--
Universal method: extension function chaining with typed return
--FILE--
<?php
use native_types;
function int_to_words(int $int): string
{
$map = [1 => '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"
Loading…
Cancel
Save