[prev in list] [next in list] [prev in thread] [next in thread]
List: php-cvs
Subject: [PHP-CVS] [php-src] PHP-8.2: Fix GH-9556 "iterable" alias "array|Traversable" breaks PHP 8.1 code
From: George Peter Banyard <noreply () php ! net>
Date: 2022-09-30 11:45:47
Message-ID: o9jYOLVTkis7KilUDnj1vWGOtXbN7yNs4JpikTgoI () main ! php ! net
[Download RAW message or body]
Author: George Peter Banyard (Girgias)
Date: 2022-09-30T12:49:15+01:00
Commit: https://github.com/php/php-src/commit/c801076d8bd7e5d31b0dfbdc8e4e3d26fd242738
Raw diff: https://github.com/php/php-src/commit/c801076d8bd7e5d31b0dfbdc8e4e3d26fd242738.diff
Fix GH-9556 "iterable" alias "array|Traversable" breaks PHP 8.1 code
Closes GH-9558
Changed paths:
A Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt
A Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt
A Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt
A Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt
A Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt
M Zend/zend_compile.c
Diff:
diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt \
b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt new \
file mode 100644 index 000000000000..3a99d3a5d520
--- /dev/null
+++ b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt
@@ -0,0 +1,14 @@
+--TEST--
+A DNF type which contains object is redundant
+--FILE--
+<?php
+
+interface A {}
+interface B {}
+
+function test(): (A&B)|object {}
+
+?>
+===DONE===
+--EXPECTF--
+Fatal error: Type (A&B)|object contains both object and a class type, which is \
redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt \
b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt \
new file mode 100644 index 000000000000..c37f08d6dc41
--- /dev/null
+++ b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt
@@ -0,0 +1,14 @@
+--TEST--
+A DNF type which contains object is redundant 2
+--FILE--
+<?php
+
+interface A {}
+interface B {}
+
+function test(): object|(A&B) {}
+
+?>
+===DONE===
+--EXPECTF--
+Fatal error: Type (A&B)|object contains both object and a class type, which is \
redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt new \
file mode 100644 index 000000000000..b11671bc0924
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with array should be redundant
+--FILE--
+<?php
+
+function bar(): array|iterable|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Duplicate type array is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt new \
file mode 100644 index 000000000000..6973901cb5a2
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with array should be redundant
+--FILE--
+<?php
+
+function bar(): iterable|array|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Duplicate type array is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt new \
file mode 100644 index 000000000000..e8fa3c040261
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with second iterable should be redundant
+--FILE--
+<?php
+
+function bar(): iterable|iterable|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Duplicate type array is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt new \
file mode 100644 index 000000000000..b7a70191145f
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt
@@ -0,0 +1,13 @@
+--TEST--
+iterable type with object should NOT be redundant 1
+--FILE--
+<?php
+
+function bar(): iterable|object|null {
+ return null;
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt new \
file mode 100644 index 000000000000..07a666823295
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt
@@ -0,0 +1,13 @@
+--TEST--
+iterable type with object should NOT be redundant 2
+--FILE--
+<?php
+
+function bar(): object|iterable|null {
+ return null;
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt new \
file mode 100644 index 000000000000..eedf16fd7649
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with object and class T should be redundant
+--FILE--
+<?php
+
+function bar(): object|iterable|T|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Type Traversable|T|object|array|null contains both object and a class \
type, which is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt new \
file mode 100644 index 000000000000..acad787130a6
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with object and class T should be redundant
+--FILE--
+<?php
+
+function bar(): iterable|object|T|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Type Traversable|T|object|array|null contains both object and a class \
type, which is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt new \
file mode 100644 index 000000000000..84ba505aa7da
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with object and class T should be redundant
+--FILE--
+<?php
+
+function bar(): T|object|iterable|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Type T|Traversable|object|array|null contains both object and a class \
type, which is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt new \
file mode 100644 index 000000000000..541317d1d696
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt
@@ -0,0 +1,12 @@
+--TEST--
+iterable type with object and class T should be redundant
+--FILE--
+<?php
+
+function bar(): T|iterable|object|null {
+ return null;
+}
+
+?>
+--EXPECTF--
+Fatal error: Type T|Traversable|object|array|null contains both object and a class \
type, which is redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt \
b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt
new file mode 100644
index 000000000000..158b6c2214f4
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt
@@ -0,0 +1,18 @@
+--TEST--
+iterable type with object should be allowed in variance checks
+--FILE--
+<?php
+
+class A {
+ public object|iterable $x;
+ public object|array $y;
+}
+class B extends A {
+ public object|array $x;
+ public object|iterable $y;
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt \
b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt
new file mode 100644
index 000000000000..bc9852da83d1
--- /dev/null
+++ b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Using both object and a class type 2
+--FILE--
+<?php
+
+function test(): Test|object {
+}
+
+?>
+--EXPECTF--
+Fatal error: Type Test|object contains both object and a class type, which is \
redundant in %s on line %d
diff --git a/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt \
b/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt \
new file mode 100644 index 000000000000..3fbb9a29fe5a
--- /dev/null
+++ b/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt
@@ -0,0 +1,12 @@
+--TEST--
+object and static are redundant 2
+--FILE--
+<?php
+
+class Test {
+ public function foo(): object|static {}
+}
+
+?>
+--EXPECTF--
+Fatal error: Type static|object contains both object and a class type, which is \
redundant in %s on line %d
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index f1dce379ae86..154c5a810ba6 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6363,6 +6363,7 @@ static zend_type zend_compile_typename(
zend_ast_list *list = zend_ast_get_list(ast);
zend_type_list *type_list;
bool is_composite = false;
+ bool has_only_iterable_class = true;
ALLOCA_FLAG(use_heap)
type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
@@ -6371,8 +6372,10 @@ static zend_type zend_compile_typename(
for (uint32_t i = 0; i < list->children; i++) {
zend_ast *type_ast = list->child[i];
zend_type single_type;
+ uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
if (type_ast->kind == ZEND_AST_TYPE_INTERSECTION) {
+ has_only_iterable_class = false;
is_composite = true;
/* The first class type can be stored directly as the type ptr payload. */
if (ZEND_TYPE_IS_COMPLEX(type) && !ZEND_TYPE_HAS_LIST(type)) {
@@ -6380,8 +6383,9 @@ static zend_type zend_compile_typename(
type_list->num_types = 1;
type_list->types[0] = type;
ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
- ZEND_TYPE_SET_LIST(type, type_list);
}
+ /* Mark type as list type */
+ ZEND_TYPE_SET_LIST(type, type_list);
single_type = zend_compile_typename(type_ast, false);
ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(single_type));
@@ -6406,6 +6410,9 @@ static zend_type zend_compile_typename(
if (single_type_mask == MAY_BE_ANY) {
zend_error_noreturn(E_COMPILE_ERROR, "Type mixed can only be used as a \
standalone type"); }
+ if (ZEND_TYPE_IS_COMPLEX(single_type) && \
!ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) { + has_only_iterable_class = false;
+ }
uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask;
if (type_mask_overlap) {
@@ -6414,8 +6421,9 @@ static zend_type zend_compile_typename(
zend_error_noreturn(E_COMPILE_ERROR,
"Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str));
}
- if ( ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_TRUE) && (single_type_mask == \
MAY_BE_FALSE))
- || ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_FALSE) && (single_type_mask == \
MAY_BE_TRUE)) ) { +
+ if ( ((type_mask & MAY_BE_TRUE) && (single_type_mask == MAY_BE_FALSE))
+ || ((type_mask & MAY_BE_FALSE) && (single_type_mask == MAY_BE_TRUE)) ) {
zend_error_noreturn(E_COMPILE_ERROR,
"Type contains both true and false, bool should be used instead");
}
@@ -6457,7 +6465,8 @@ static zend_type zend_compile_typename(
free_alloca(type_list, use_heap);
uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
- if ((type_mask & MAY_BE_OBJECT) && (ZEND_TYPE_IS_COMPLEX(type) || (type_mask & \
MAY_BE_STATIC))) { + if ((type_mask & MAY_BE_OBJECT) &&
+ ((!has_only_iterable_class && ZEND_TYPE_IS_COMPLEX(type)) || (type_mask & \
MAY_BE_STATIC))) { zend_string *type_str = zend_type_to_string(type);
zend_error_noreturn(E_COMPILE_ERROR,
"Type %s contains both object and a class type, which is redundant",
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic