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