- 添加了对函数和构造函数中命名参数的支持 - 实现了提升属性(Property Promotion)功能 - 新增了对 C++ 保留关键字作为参数名的支持 - 完善了闭包类型检查和参数验证逻辑 - 增加了内部函数调用的命名参数验证 - 优化了参数类型检查和错误提示信息 - 添加了相关测试用例验证功能正确性pull/5/head
parent
91f7085662
commit
0bfa2869c5
14 changed files with 311 additions and 15 deletions
@ -0,0 +1,82 @@ |
||||
--TEST-- |
||||
Closure composite type declarations use runtime type checks |
||||
--ENV-- |
||||
USE_ZEND_ALLOC=0 |
||||
--FILE-- |
||||
<?php |
||||
|
||||
interface ClosureIA {} |
||||
interface ClosureIB {} |
||||
class ClosureBoth implements ClosureIA, ClosureIB {} |
||||
class ClosureOnlyA implements ClosureIA {} |
||||
|
||||
function main(): void |
||||
{ |
||||
$nullable = function (?int $value) { |
||||
var_dump($value); |
||||
}; |
||||
$nullable(null); |
||||
|
||||
$union = function (int|string $union) { |
||||
var_dump($union); |
||||
}; |
||||
$union("ok"); |
||||
|
||||
$variadic = function (int|string ...$values) { |
||||
var_dump($values); |
||||
}; |
||||
$variadic(1, "two"); |
||||
|
||||
$intersection = function (ClosureIA&ClosureIB $value) { |
||||
var_dump(get_class($value)); |
||||
}; |
||||
$intersection(new ClosureBoth()); |
||||
|
||||
$returnUnion = function ($value): int|string { |
||||
return $value; |
||||
}; |
||||
var_dump($returnUnion(42)); |
||||
|
||||
try { |
||||
$nullable("bad"); |
||||
} catch (\TypeError $e) { |
||||
echo $e->getMessage(), "\n"; |
||||
} |
||||
try { |
||||
$union([]); |
||||
} catch (\TypeError $e) { |
||||
echo $e->getMessage(), "\n"; |
||||
} |
||||
try { |
||||
$variadic(1, []); |
||||
} catch (\TypeError $e) { |
||||
echo $e->getMessage(), "\n"; |
||||
} |
||||
try { |
||||
$intersection(new ClosureOnlyA()); |
||||
} catch (\TypeError $e) { |
||||
echo $e->getMessage(), "\n"; |
||||
} |
||||
try { |
||||
$returnUnion([]); |
||||
} catch (\TypeError $e) { |
||||
echo $e->getMessage(), "\n"; |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
NULL |
||||
string(2) "ok" |
||||
array(2) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
string(3) "two" |
||||
} |
||||
string(11) "ClosureBoth" |
||||
int(42) |
||||
{closure}(): Argument #1 ($value) must be of type ?int, string given |
||||
{closure}(): Argument #1 ($union) must be of type int|string, array given |
||||
{closure}(): Argument #2 ($values) must be of type int|string, array given |
||||
{closure}(): Argument #1 ($value) must be of type ClosureIA&ClosureIB, object given |
||||
{closure}(): Return value must be of type int|string, array given |
||||
@ -0,0 +1,41 @@ |
||||
--TEST-- |
||||
Closure parameters handle defaults and variadic arguments |
||||
--ENV-- |
||||
USE_ZEND_ALLOC=0 |
||||
--FILE-- |
||||
<?php |
||||
function main(): void |
||||
{ |
||||
$default = function ($value = 42) { |
||||
var_dump($value); |
||||
}; |
||||
$default(); |
||||
|
||||
$variadic = function (...$values) { |
||||
var_dump($values); |
||||
}; |
||||
$variadic(1, "two", null); |
||||
|
||||
$required = function (?int $value) { |
||||
var_dump($value); |
||||
}; |
||||
try { |
||||
$required(); |
||||
} catch (\Throwable $e) { |
||||
var_dump(get_class($e)); |
||||
var_dump($e->getMessage()); |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(42) |
||||
array(3) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
string(3) "two" |
||||
[2]=> |
||||
NULL |
||||
} |
||||
string(18) "ArgumentCountError" |
||||
string(74) "Too few arguments to function {closure}(), 0 passed and exactly 1 expected" |
||||
@ -0,0 +1,16 @@ |
||||
--TEST-- |
||||
Internal function named arguments are validated before optimization |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(strlen(string: "abc")); |
||||
var_dump(str_replace(replace: "x", subject: "abc", search: "a")); |
||||
var_dump(substr(length: 2, string: "abcdef", offset: 3)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(3) |
||||
string(3) "xbc" |
||||
string(2) "de" |
||||
@ -0,0 +1,37 @@ |
||||
--TEST-- |
||||
Named arguments and promoted properties with C++ reserved parameter names |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function reserved_params($union, $class = 2): array |
||||
{ |
||||
return [$union, $class]; |
||||
} |
||||
|
||||
class ReservedPromotion |
||||
{ |
||||
public function __construct( |
||||
public int $union, |
||||
public string $class = "default" |
||||
) { |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(reserved_params(class: 20, union: 10)); |
||||
|
||||
$object = new ReservedPromotion(class: "named", union: 42); |
||||
var_dump($object->union); |
||||
var_dump($object->class); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(2) { |
||||
[0]=> |
||||
int(10) |
||||
[1]=> |
||||
int(20) |
||||
} |
||||
int(42) |
||||
string(5) "named" |
||||
@ -0,0 +1,21 @@ |
||||
--TEST-- |
||||
SSA optimizations handle parameters with C++ reserved names |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function sum_reserved(int $union, int $class): int |
||||
{ |
||||
$total = 0; |
||||
for ($i = 0; $i < $union; $i++) { |
||||
$total += $class; |
||||
} |
||||
return $total; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(sum_reserved(union: 4, class: 3)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(12) |
||||
Loading…
Reference in new issue