- 添加实例属性类型检查消息包含类名的测试用例 - 添加属性联合赋值操作使用运行时类型检查的测试用例 - 添加动态属性赋值TypeError捕获的测试用例 - 添加二元运算符操作数从左到右求值顺序的测试用例 - 添加原生优化调用参数从左到右求值的测试用例 - 添加构造函数属性提升联合参数检查的测试用例 fix(assign): 修复属性赋值时的类型检查问题 - 在属性赋值操作中添加对象属性类型检查包装 - 修复属性赋值表达式中的类型验证逻辑 - 添加静态属性赋值的类型检查支持 fix(ctor): 修复构造函数属性提升的参数验证顺序 - 将构造函数属性提升移到参数类型验证之后执行 - 在数组初始化计划后添加错误检查机制pull/5/head
parent
54bca6942e
commit
f8c37f91c3
11 changed files with 212 additions and 7 deletions
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
str_replace(search: "a", subject: "b"); |
||||||
|
} |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
strlen(foo: "abc"); |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
function target($a, $b): void |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
target(a: 1, ...[2]); |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
--TEST-- |
||||||
|
Constructor property promotion checks union parameter before assignment |
||||||
|
--ENV-- |
||||||
|
USE_ZEND_ALLOC=0 |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class PromotedUnionHolder |
||||||
|
{ |
||||||
|
public function __construct(public int|string $value) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
try { |
||||||
|
new PromotedUnionHolder([]); |
||||||
|
} catch (TypeError $e) { |
||||||
|
var_dump($e->getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(96) "PromotedUnionHolder::__construct(): Argument #1 ($value) must be of type int|string, array given" |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
--TEST-- |
||||||
|
Binary operator operands are evaluated left-to-right |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
function main() |
||||||
|
{ |
||||||
|
var_dump((print "sub-left\n") - (print "sub-right\n")); |
||||||
|
var_dump((print "nested-left\n") * ((print "nested-right-left\n") + (print "nested-right-right\n"))); |
||||||
|
var_dump((print "eq-left\n") == (print "eq-right\n")); |
||||||
|
var_dump((print "same-left\n") === (print "same-right\n")); |
||||||
|
var_dump((print "spaceship-left\n") <=> (print "spaceship-right\n")); |
||||||
|
var_dump((print "pow-left\n") ** (print "pow-right\n")); |
||||||
|
var_dump(((print "logic-left\n") && false && (print "logic-right\n")) + (print "logic-after\n")); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
sub-left |
||||||
|
sub-right |
||||||
|
int(0) |
||||||
|
nested-left |
||||||
|
nested-right-left |
||||||
|
nested-right-right |
||||||
|
int(2) |
||||||
|
eq-left |
||||||
|
eq-right |
||||||
|
bool(true) |
||||||
|
same-left |
||||||
|
same-right |
||||||
|
bool(true) |
||||||
|
spaceship-left |
||||||
|
spaceship-right |
||||||
|
int(0) |
||||||
|
pow-left |
||||||
|
pow-right |
||||||
|
int(1) |
||||||
|
logic-left |
||||||
|
logic-after |
||||||
|
int(1) |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
--TEST-- |
||||||
|
Native optimized calls evaluate arguments left-to-right |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
var_dump(str_repeat((print "repeat-left\n") ? "x" : "x", (print "repeat-right\n") + 1)); |
||||||
|
var_dump(round((print "round-left\n") + 1.25, (print "round-right\n"))); |
||||||
|
var_dump(strcmp((print "cmp-left\n") ? "a" : "a", (print "cmp-right\n") ? "b" : "b")); |
||||||
|
$text = '<x>'; |
||||||
|
var_dump($text->replace((print "method-left\n") ? "x" : "x", (print "method-right\n") ? "y" : "y")); |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
repeat-left |
||||||
|
repeat-right |
||||||
|
string(2) "xx" |
||||||
|
round-left |
||||||
|
round-right |
||||||
|
float(2.3) |
||||||
|
cmp-left |
||||||
|
cmp-right |
||||||
|
int(-1) |
||||||
|
method-left |
||||||
|
method-right |
||||||
|
string(3) "<y>" |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
--TEST-- |
||||||
|
type hits: instance property type check message includes class name |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class TypeHitPropertyMessage |
||||||
|
{ |
||||||
|
public int|string $union; |
||||||
|
|
||||||
|
public function setInvalid(): void |
||||||
|
{ |
||||||
|
try { |
||||||
|
$this->union = null; |
||||||
|
} catch (TypeError $e) { |
||||||
|
var_dump($e->getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main() |
||||||
|
{ |
||||||
|
(new TypeHitPropertyMessage())->setInvalid(); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(69) "TypeHitPropertyMessage::$union must be of type int|string, null given" |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
--TEST-- |
||||||
|
type hits: property coalesce assignment uses runtime type check |
||||||
|
--ENV-- |
||||||
|
USE_ZEND_ALLOC=0 |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class TypeHitCoalesceProperty |
||||||
|
{ |
||||||
|
public int|string $union; |
||||||
|
|
||||||
|
public function run(): void |
||||||
|
{ |
||||||
|
try { |
||||||
|
$this->union ??= null; |
||||||
|
} catch (TypeError $e) { |
||||||
|
var_dump($e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
$this->union = "ok"; |
||||||
|
$this->union ??= null; |
||||||
|
var_dump($this->union); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
(new TypeHitCoalesceProperty())->run(); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(70) "TypeHitCoalesceProperty::$union must be of type int|string, null given" |
||||||
|
string(2) "ok" |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
--TEST-- |
||||||
|
AOT dynamic property assignment TypeError can be caught |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class TypeHitDynamicProperty { |
||||||
|
public int|string $union; |
||||||
|
} |
||||||
|
|
||||||
|
function assign_dynamic(TypeHitDynamicProperty $obj, string $prop, mixed $value): void { |
||||||
|
try { |
||||||
|
$obj->$prop = $value; |
||||||
|
var_dump('not reached'); |
||||||
|
} catch (TypeError $e) { |
||||||
|
var_dump(get_class($e)); |
||||||
|
var_dump(str_contains($e->getMessage(), 'Cannot assign null to property TypeHitDynamicProperty::$union')); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void |
||||||
|
{ |
||||||
|
$obj = new TypeHitDynamicProperty(); |
||||||
|
assign_dynamic($obj, 'union', null); |
||||||
|
$obj->union = 'ok'; |
||||||
|
var_dump($obj->union); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
string(9) "TypeError" |
||||||
|
bool(true) |
||||||
|
string(2) "ok" |
||||||
Loading…
Reference in new issue