- 添加了对函数和构造函数中命名参数的支持 - 实现了提升属性(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