Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 06030cf

Browse files
committed
Add tests to check ZPP handles intersection types for internal functions
1 parent 4457dba commit 06030cf

File tree

5 files changed

+142
-20
lines changed

5 files changed

+142
-20
lines changed

‎ext/zend_test/test.c‎

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,51 @@ static ZEND_FUNCTION(zend_string_or_stdclass)
206206
}
207207
}
208208

209+
/* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
210+
static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
211+
{
212+
zend_string *str;
213+
zend_object *object;
214+
215+
ZEND_PARSE_PARAMETERS_START(1, 1)
216+
Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(object, zend_standard_class_def, str)
217+
ZEND_PARSE_PARAMETERS_END();
218+
219+
if (str) {
220+
RETURN_STR_COPY(str);
221+
} else if (object) {
222+
RETURN_OBJ_COPY(object);
223+
} else {
224+
RETURN_NULL();
225+
}
226+
}
227+
228+
static ZEND_FUNCTION(zend_intersection_type)
229+
{
230+
zend_object *object;
231+
232+
ZEND_PARSE_PARAMETERS_START(1, 1)
233+
Z_PARAM_OBJ(object)
234+
ZEND_PARSE_PARAMETERS_END();
235+
236+
if (!(instanceof_function(object->ce, zend_ce_countable) && instanceof_function(object->ce, zend_ce_traversable))) {
237+
zend_argument_type_error(1, "must be of type Traversable&Countable, %s given", ZSTR_VAL(object->ce->name));
238+
}
239+
240+
RETURN_OBJ_COPY(object);
241+
}
242+
243+
static ZEND_FUNCTION(zend_intersection_type_return)
244+
{
245+
zend_object *object;
246+
247+
ZEND_PARSE_PARAMETERS_START(1, 1)
248+
Z_PARAM_OBJ(object)
249+
ZEND_PARSE_PARAMETERS_END();
250+
251+
RETURN_OBJ_COPY(object);
252+
}
253+
209254
static ZEND_FUNCTION(zend_test_compile_string)
210255
{
211256
zend_string *source_string = NULL;
@@ -241,25 +286,6 @@ static ZEND_FUNCTION(zend_test_compile_string)
241286
return;
242287
}
243288

244-
/* Tests Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL */
245-
static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
246-
{
247-
zend_string *str;
248-
zend_object *object;
249-
250-
ZEND_PARSE_PARAMETERS_START(1, 1)
251-
Z_PARAM_OBJ_OF_CLASS_OR_STR_OR_NULL(object, zend_standard_class_def, str)
252-
ZEND_PARSE_PARAMETERS_END();
253-
254-
if (str) {
255-
RETURN_STR_COPY(str);
256-
} else if (object) {
257-
RETURN_OBJ_COPY(object);
258-
} else {
259-
RETURN_NULL();
260-
}
261-
}
262-
263289
static ZEND_FUNCTION(zend_weakmap_attach)
264290
{
265291
zval *value;

‎ext/zend_test/test.stub.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ function zend_string_or_stdclass($param): stdClass|string {}
119119
/** @param stdClass|string|null $param */
120120
function zend_string_or_stdclass_or_null($param): stdClass|string|null {}
121121

122+
function zend_intersection_type(Traversable&Countable $v): Traversable&Countable {}
123+
124+
function zend_intersection_type_return(object $v): Traversable&Countable {}
125+
122126
function zend_iterable(iterable $arg1, ?iterable $arg2 = null): void {}
123127

124128
function zend_weakmap_attach(object $object, mixed $value): bool {}

‎ext/zend_test/test_arginfo.h‎

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Test that internal functions can accept intersection types via ZPP
3+
--EXTENSIONS--
4+
zend_test
5+
spl
6+
--FILE--
7+
<?php
8+
9+
class C implements Countable {
10+
public function count(): int {
11+
return 1;
12+
}
13+
}
14+
15+
class I extends EmptyIterator implements Countable {
16+
public function count(): int {
17+
return 1;
18+
}
19+
}
20+
21+
22+
try {
23+
zend_intersection_type(new EmptyIterator());
24+
} catch (TypeError $e) {
25+
echo $e->getMessage(), PHP_EOL;
26+
}
27+
try {
28+
zend_intersection_type(new C());
29+
} catch (TypeError $e) {
30+
echo $e->getMessage(), PHP_EOL;
31+
}
32+
33+
zend_intersection_type(new I());
34+
35+
?>
36+
==DONE==
37+
--EXPECT--
38+
zend_intersection_type(): Argument #1 ($v) must be of type Traversable&Countable, EmptyIterator given
39+
zend_intersection_type(): Argument #1 ($v) must be of type Traversable&Countable, C given
40+
==DONE==
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Test that internal functions warn on improper intersection types return
3+
--EXTENSIONS--
4+
zend_test
5+
spl
6+
--FILE--
7+
<?php
8+
9+
class C implements Countable {
10+
public function count(): int {
11+
return 1;
12+
}
13+
}
14+
15+
class I extends EmptyIterator implements Countable {
16+
public function count(): int {
17+
return 1;
18+
}
19+
}
20+
21+
try {
22+
var_dump(zend_intersection_type(new EmptyIterator()));
23+
} catch (TypeError $e) {
24+
echo $e->getMessage(), PHP_EOL;
25+
}
26+
try {
27+
var_dump(zend_intersection_type(new C()));
28+
} catch (TypeError $e) {
29+
echo $e->getMessage(), PHP_EOL;
30+
}
31+
var_dump(zend_intersection_type(new I()));
32+
33+
?>
34+
==DONE==
35+
--EXPECT--
36+
zend_intersection_type(): Argument #1 ($v) must be of type Traversable&Countable, EmptyIterator given
37+
zend_intersection_type(): Argument #1 ($v) must be of type Traversable&Countable, C given
38+
object(I)#2 (0) {
39+
}
40+
==DONE==

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /