Skip to content

Commit 2b59df1

Browse files
committed
Add support for tentative return types of internal methods
RFC: https://wiki.php.net/rfc/internal_method_return_types
1 parent 32aff25 commit 2b59df1

36 files changed

+631
-293
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4003,7 +4003,7 @@ uint32_t zend_get_return_info_from_signature_only(
40034003
const zend_function *func, const zend_script *script,
40044004
zend_class_entry **ce, bool *ce_is_instanceof) {
40054005
uint32_t type;
4006-
if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4006+
if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && !ZEND_ARG_TYPE_IS_TENTATIVE(func->common.arg_info - 1)) {
40074007
zend_arg_info *ret_info = func->common.arg_info - 1;
40084008
type = zend_fetch_arg_info_type(script, ret_info, ce);
40094009
*ce_is_instanceof = ce != NULL;
@@ -4025,15 +4025,16 @@ uint32_t zend_get_return_info_from_signature_only(
40254025
ZEND_API void zend_init_func_return_info(
40264026
const zend_op_array *op_array, const zend_script *script, zend_ssa_var_info *ret)
40274027
{
4028-
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4029-
zend_ssa_range tmp_range = {0, 0, 0, 0};
4030-
bool is_instanceof = false;
4031-
ret->type = zend_get_return_info_from_signature_only(
4032-
(zend_function *) op_array, script, &ret->ce, &is_instanceof);
4033-
ret->is_instanceof = is_instanceof;
4034-
ret->range = tmp_range;
4035-
ret->has_range = 0;
4036-
}
4028+
ZEND_ASSERT((op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE));
4029+
ZEND_ASSERT(!ZEND_ARG_TYPE_IS_TENTATIVE(&((zend_function *) op_array)->common.arg_info[-1]));
4030+
4031+
zend_ssa_range tmp_range = {0, 0, 0, 0};
4032+
bool is_instanceof = false;
4033+
ret->type = zend_get_return_info_from_signature_only(
4034+
(zend_function *) op_array, script, &ret->ce, &is_instanceof);
4035+
ret->is_instanceof = is_instanceof;
4036+
ret->range = tmp_range;
4037+
ret->has_range = 0;
40374038
}
40384039

40394040
void zend_func_return_info(const zend_op_array *op_array,

Zend/Optimizer/zend_optimizer.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,9 @@ ZEND_API int zend_optimize_script(zend_script *script, zend_long optimization_le
14461446
func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
14471447
if (func_info) {
14481448
func_info->call_map = zend_build_call_map(&ctx.arena, func_info, call_graph.op_arrays[i]);
1449-
if (call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1449+
if ((call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) &&
1450+
!ZEND_ARG_TYPE_IS_TENTATIVE(&((zend_function *) call_graph.op_arrays[i])->common.arg_info[-1])
1451+
) {
14501452
zend_init_func_return_info(call_graph.op_arrays[i], script, &func_info->return_info);
14511453
}
14521454
}

Zend/tests/parameter_default_values/internal_declaration_error_class_const.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ The default value is a class constant in the parent class method's signature.
44
<?php
55
class MyDateTimeZone extends DateTimeZone
66
{
7-
public static function listIdentifiers()
7+
public static function listIdentifiers(): array
88
{
99
}
1010
}
1111
?>
1212
--EXPECTF--
13-
Fatal error: Declaration of MyDateTimeZone::listIdentifiers() must be compatible with DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null) in %s on line %d
13+
Fatal error: Declaration of MyDateTimeZone::listIdentifiers(): array must be compatible with DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array in %s on line %d

Zend/tests/parameter_default_values/internal_declaration_error_const.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ The default value is a constant in the parent class method's signature.
44
<?php
55
class MyDateTimeZone extends DateTimeZone
66
{
7-
public function getTransitions()
7+
public function getTransitions(): array|false
88
{
99
}
1010
}
1111
?>
1212
--EXPECTF--
13-
Fatal error: Declaration of MyDateTimeZone::getTransitions() must be compatible with DateTimeZone::getTransitions(int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX) in %s on line %d
13+
Fatal error: Declaration of MyDateTimeZone::getTransitions(): array|false must be compatible with DateTimeZone::getTransitions(int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX): array|false in %s on line %d

Zend/tests/parameter_default_values/internal_declaration_error_false.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ The default value is false in the parent class method's signature.
55

66
interface MyDateTimeInterface extends DateTimeInterface
77
{
8-
public function diff();
8+
public function diff(): DateInterval;
99
}
1010
?>
1111
--EXPECTF--
12-
Fatal error: Declaration of MyDateTimeInterface::diff() must be compatible with DateTimeInterface::diff(DateTimeInterface $targetObject, bool $absolute = false) in %s on line %d
12+
Fatal error: Declaration of MyDateTimeInterface::diff(): DateInterval must be compatible with DateTimeInterface::diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval in %s on line %d

Zend/tests/parameter_default_values/internal_declaration_error_int.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ The default value is an integer in the parent class method's signature.
44
<?php
55
class MyDateTime extends DateTime
66
{
7-
public function setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false)
7+
public function setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false): DateTime
88
{
99
}
1010
}
1111
?>
1212
--EXPECTF--
13-
Fatal error: Declaration of MyDateTime::setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false) must be compatible with DateTime::setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0) in %s on line %d
13+
Fatal error: Declaration of MyDateTime::setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false): DateTime must be compatible with DateTime::setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTime in %s on line %d

Zend/tests/parameter_default_values/internal_declaration_error_null.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ The default value is null in the parent class method's signature.
44
<?php
55
class MyDateTime extends DateTime
66
{
7-
public static function createFromFormat()
7+
public static function createFromFormat(): DateTime|false
88
{
99
}
1010
}
1111
?>
1212
--EXPECTF--
13-
Fatal error: Declaration of MyDateTime::createFromFormat() must be compatible with DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) in %s on line %d
13+
Fatal error: Declaration of MyDateTime::createFromFormat(): DateTime|false must be compatible with DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|false in %s on line %d
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Test that no notice is emitted when the return type/value of the overriding method is compatible with the tentative return type/value of the overridden method
3+
--FILE--
4+
<?php
5+
class MyDateTimeZone extends DateTimeZone
6+
{
7+
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array
8+
{
9+
return [];
10+
}
11+
}
12+
13+
var_dump(MyDateTimeZone::listIdentifiers());
14+
?>
15+
--EXPECT--
16+
array(0) {
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Test that a notice is emitted when the return type/value of the overriding method is incompatible with the tentative return type/value of the overridden method
3+
--FILE--
4+
<?php
5+
class MyDateTimeZone extends DateTimeZone
6+
{
7+
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): string
8+
{
9+
return "";
10+
}
11+
}
12+
13+
var_dump(MyDateTimeZone::listIdentifiers());
14+
?>
15+
--EXPECTF--
16+
Deprecated: Declaration of MyDateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): string should be compatible with DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array in %s on line %d
17+
string(0) ""
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Internal class as parent
3+
--FILE--
4+
<?php
5+
6+
class Test extends DateTime {
7+
public static function createFromFormat($format, $datetime, Wrong $timezone = null): DateTime|false {}
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Could not check compatibility between Test::createFromFormat($format, $datetime, ?Wrong $timezone = null): DateTime|false and DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|false, because class Wrong is not available in %s on line %d

Zend/tests/type_declarations/variance/internal_parent.phpt renamed to Zend/tests/type_declarations/variance/internal_parent/internal_parent2.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Internal class as parent
44
<?php
55

66
class Test extends DateTime {
7-
public static function createFromFormat($format, $datetime, Wrong $timezone = null) { }
7+
public static function createFromFormat($format, $datetime, $timezone = null): Wrong { }
88
}
99

1010
?>
1111
--EXPECTF--
12-
Fatal error: Could not check compatibility between Test::createFromFormat($format, $datetime, ?Wrong $timezone = null) and DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null), because class Wrong is not available in %s on line %d
12+
Fatal error: Could not check compatibility between Test::createFromFormat($format, $datetime, $timezone = null): Wrong and DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|false, because class Wrong is not available in %s on line %d
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Test that a notice is emitted when the tentative return type of the overridden method is omitted
3+
--FILE--
4+
<?php
5+
class MyDateTimeZone extends DateTimeZone
6+
{
7+
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null)
8+
{
9+
}
10+
}
11+
?>
12+
--EXPECTF--
13+
Deprecated: Declaration of MyDateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null) should be compatible with DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Test that the notice can be suppressed when the return type/value of the overriding method is incompatible with the tentative return type/value of the overridden method
3+
--FILE--
4+
<?php
5+
6+
class MyDateTime extends DateTime
7+
{
8+
/**
9+
* @return DateTime|false
10+
*/
11+
#[ReturnTypeWillChange]
12+
public function modify(string $modifier) {
13+
return false;
14+
}
15+
}
16+
17+
$date = new MyDateTime("2021-01-01 00:00:00");
18+
var_dump($date->modify("+1 sec"));
19+
?>
20+
--EXPECT--
21+
bool(false)

Zend/zend_API.h

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -107,66 +107,97 @@ typedef struct _zend_fcall_info_cache {
107107

108108
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
109109

110-
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \
111-
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0))
110+
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic, is_tentative) \
111+
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0) | ((is_tentative) ? _ZEND_IS_TENTATIVE_BIT : 0))
112112

113113
/* Arginfo structures without type information */
114114
#define ZEND_ARG_INFO(pass_by_ref, name) \
115-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
115+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
116116
#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \
117-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
117+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
118118
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
119-
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
119+
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
120120
/* Arginfo structures with simple type information */
121121
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
122-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
122+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
123123
#define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \
124-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
124+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
125125
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
126-
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
126+
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
127127
/* Arginfo structures with complex type information */
128128
#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \
129-
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
129+
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
130130
#define ZEND_ARG_OBJ_TYPE_MASK(pass_by_ref, name, class_name, type_mask, default_value) \
131-
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
131+
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
132132
/* Arginfo structures with object type information */
133133
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
134-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
134+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
135135
#define ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, classname, allow_null, default_value) \
136-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
136+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
137137
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
138-
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
138+
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
139139
/* Legacy arginfo structures */
140140
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \
141-
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
141+
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
142142
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \
143-
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
143+
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
144144

145-
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
145+
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, is_tentative_return_type) \
146146
static const zend_internal_arg_info name[] = { \
147147
{ (const char*)(zend_uintptr_t)(required_num_args), \
148-
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
148+
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
149+
150+
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
151+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, 0)
152+
153+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
154+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, 1)
149155

150156
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
151-
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
157+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, 0, -1, class_name, allow_null, 0)
158+
159+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO(name, class_name, allow_null) \
160+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, 0, -1, class_name, allow_null, 1)
161+
162+
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, is_tentative_return_type) \
163+
static const zend_internal_arg_info name[] = { \
164+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
152165

153166
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
167+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, 0)
168+
169+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
170+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, 1)
171+
172+
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, is_tentative_return_type) \
154173
static const zend_internal_arg_info name[] = { \
155-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
174+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
156175

157176
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
177+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, 0)
178+
179+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
180+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, 1)
181+
182+
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, is_tentative_return_type) \
158183
static const zend_internal_arg_info name[] = { \
159-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
184+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
160185

161186
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
162-
static const zend_internal_arg_info name[] = { \
163-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
187+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, 0)
188+
189+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
190+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, 1)
191+
164192
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
165-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
193+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, 0, -1, type, allow_null, 0)
194+
195+
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO(name, type, allow_null) \
196+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, 0, -1, type, allow_null, 1)
166197

167198
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
168199
static const zend_internal_arg_info name[] = { \
169-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
200+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0, 0)), NULL },
170201
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
171202
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
172203
#define ZEND_END_ARG_INFO() };

0 commit comments

Comments
 (0)