Add support for tentative return types of internal methods

RFC: https://wiki.php.net/rfc/internal_method_return_types

Closses GH-6971
This commit is contained in:
Máté Kocsis committed 2021-05-14 15:55:25 +02:00
1 parent 008bfcc7ba
commit 532c60cb92
39 files changed
+668 -291

No files matched your search

+4
View File
@@ -57,6 +57,10 @@ PHP 8.1 UPGRADE NOTES
This means that static variables in methods now behave the same way as
static properties.
RFC: https://wiki.php.net/rfc/static_variable_inheritance
. Most non-final internal methods now require overriding methods to declare a
compatible return type, otherwise a deprecated notice is emitted during
inheritance validation.
RFC: https://wiki.php.net/rfc/internal_method_return_types
- Fileinfo:
. The fileinfo functions now accept and return, respectively, finfo objects
+2 -2
View File
@@ -844,7 +844,7 @@ ZEND_API uint32_t zend_get_func_info(
#endif
ret = zend_get_return_info_from_signature_only(
callee_func, /* script */ NULL, ce, ce_is_instanceof);
callee_func, /* script */ NULL, ce, ce_is_instanceof, /* use_tentative_return_info */ !call_info->is_prototype);
#if ZEND_DEBUG
if (internal_ret) {
@@ -884,7 +884,7 @@ ZEND_API uint32_t zend_get_func_info(
}
if (!ret) {
ret = zend_get_return_info_from_signature_only(
callee_func, /* TODO: script */ NULL, ce, ce_is_instanceof);
callee_func, /* TODO: script */ NULL, ce, ce_is_instanceof, /* use_tentative_return_info */ !call_info->is_prototype);
}
}
return ret;
+13 -11
View File
@@ -4001,9 +4001,11 @@ static int is_recursive_tail_call(const zend_op_array *op_array,
uint32_t zend_get_return_info_from_signature_only(
const zend_function *func, const zend_script *script,
zend_class_entry **ce, bool *ce_is_instanceof) {
zend_class_entry **ce, bool *ce_is_instanceof, bool use_tentative_return_info) {
uint32_t type;
if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
if (func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE &&
(use_tentative_return_info || !ZEND_ARG_TYPE_IS_TENTATIVE(func->common.arg_info - 1))
) {
zend_arg_info *ret_info = func->common.arg_info - 1;
type = zend_fetch_arg_info_type(script, ret_info, ce);
*ce_is_instanceof = ce != NULL;
@@ -4025,15 +4027,15 @@ uint32_t zend_get_return_info_from_signature_only(
ZEND_API void zend_init_func_return_info(
const zend_op_array *op_array, const zend_script *script, zend_ssa_var_info *ret)
{
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_ssa_range tmp_range = {0, 0, 0, 0};
bool is_instanceof = false;
ret->type = zend_get_return_info_from_signature_only(
(zend_function *) op_array, script, &ret->ce, &is_instanceof);
ret->is_instanceof = is_instanceof;
ret->range = tmp_range;
ret->has_range = 0;
}
ZEND_ASSERT((op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE));
zend_ssa_range tmp_range = {0, 0, 0, 0};
bool is_instanceof = false;
ret->type = zend_get_return_info_from_signature_only(
(zend_function *) op_array, script, &ret->ce, &is_instanceof, /* use_tentative_return_info */ 1);
ret->is_instanceof = is_instanceof;
ret->range = tmp_range;
ret->has_range = 0;
}
void zend_func_return_info(const zend_op_array *op_array,
+1 -1
View File
@@ -271,7 +271,7 @@ ZEND_API void zend_init_func_return_info(
const zend_op_array *op_array, const zend_script *script, zend_ssa_var_info *ret);
uint32_t zend_get_return_info_from_signature_only(
const zend_function *func, const zend_script *script,
zend_class_entry **ce, bool *ce_is_instanceof);
zend_class_entry **ce, bool *ce_is_instanceof, bool use_tentative_return_info);
void zend_func_return_info(const zend_op_array *op_array,
const zend_script *script,
int recursive,
@@ -4,10 +4,10 @@ The default value is a class constant in the parent class method's signature.
<?php
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers()
public static function listIdentifiers(): array
{
}
}
?>
--EXPECTF--
Fatal error: Declaration of MyDateTimeZone::listIdentifiers() must be compatible with DateTimeZone::listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null) in %s on line %d
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
@@ -4,10 +4,10 @@ The default value is a constant in the parent class method's signature.
<?php
class MyDateTimeZone extends DateTimeZone
{
public function getTransitions()
public function getTransitions(): array|false
{
}
}
?>
--EXPECTF--
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
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
@@ -5,8 +5,8 @@ The default value is false in the parent class method's signature.
interface MyDateTimeInterface extends DateTimeInterface
{
public function diff();
public function diff(): DateInterval;
}
?>
--EXPECTF--
Fatal error: Declaration of MyDateTimeInterface::diff() must be compatible with DateTimeInterface::diff(DateTimeInterface $targetObject, bool $absolute = false) in %s on line %d
Fatal error: Declaration of MyDateTimeInterface::diff(): DateInterval must be compatible with DateTimeInterface::diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval in %s on line %d
@@ -4,10 +4,10 @@ The default value is an integer in the parent class method's signature.
<?php
class MyDateTime extends DateTime
{
public function setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false)
public function setTime(int $hour, int $minute, int $second = 0, bool $microsecond = false): DateTime
{
}
}
?>
--EXPECTF--
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
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
@@ -4,10 +4,10 @@ The default value is null in the parent class method's signature.
<?php
class MyDateTime extends DateTime
{
public static function createFromFormat()
public static function createFromFormat(): DateTime|false
{
}
}
?>
--EXPECTF--
Fatal error: Declaration of MyDateTime::createFromFormat() must be compatible with DateTime::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) in %s on line %d
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
@@ -1,12 +0,0 @@
--TEST--
Internal class as parent
--FILE--
<?php
class Test extends DateTime {
public static function createFromFormat($format, $datetime, Wrong $timezone = null) { }
}
?>
--EXPECTF--
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
@@ -0,0 +1,17 @@
--TEST--
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
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array
{
return [];
}
}
var_dump(MyDateTimeZone::listIdentifiers());
?>
--EXPECT--
array(0) {
}
@@ -0,0 +1,17 @@
--TEST--
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
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): string
{
return "";
}
}
var_dump(MyDateTimeZone::listIdentifiers());
?>
--EXPECTF--
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
string(0) ""
@@ -0,0 +1,13 @@
--TEST--
Test that a notice is emitted when the tentative return type of the overridden method is omitted
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null)
{
}
}
?>
--EXPECTF--
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
@@ -0,0 +1,12 @@
--TEST--
Test unresolvable inheritance check due to unavailable parameter type when the parent has a tentative return type.
--FILE--
<?php
class Test extends DateTime {
public static function createFromFormat($format, $datetime, Wrong $timezone = null): DateTime|false {}
}
?>
--EXPECTF--
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
@@ -0,0 +1,12 @@
--TEST--
Test unresolvable inheritance check due to unavailable return type when the parent has a tentative return type.
--FILE--
<?php
class Test extends DateTime {
public static function createFromFormat($format, $datetime, $timezone = null): Wrong { }
}
?>
--EXPECTF--
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
@@ -0,0 +1,13 @@
--TEST--
Test that the ReturnTypeWillChange attribute cannot target classes
--FILE--
<?php
#[ReturnTypeWillChange]
class Foo
{
}
?>
--EXPECTF--
Fatal error: Attribute "ReturnTypeWillChange" cannot target class (allowed targets: method) in %s on line %d
@@ -0,0 +1,11 @@
--TEST--
Test that the ReturnTypeWillChange attribute cannot target functions
--FILE--
<?php
#[ReturnTypeWillChange]
function foo() {}
?>
--EXPECTF--
Fatal error: Attribute "ReturnTypeWillChange" cannot target function (allowed targets: method) in %s on line %d
@@ -0,0 +1,14 @@
--TEST--
Test that the ReturnTypeWillChange attribute cannot be used with functions
--FILE--
<?php
class Foo
{
#[ReturnTypeWillChange]
public int $bar;
}
?>
--EXPECTF--
Fatal error: Attribute "ReturnTypeWillChange" cannot target property (allowed targets: method) in %s on line %d
@@ -0,0 +1,21 @@
--TEST--
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
--FILE--
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[ReturnTypeWillChange]
public function modify(string $modifier) {
return false;
}
}
$date = new MyDateTime("2021-01-01 00:00:00");
var_dump($date->modify("+1 sec"));
?>
--EXPECT--
bool(false)
+49 -24
View File
@@ -107,66 +107,91 @@ typedef struct _zend_fcall_info_cache {
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0))
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic, is_tentative) \
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0) | ((is_tentative) ? _ZEND_IS_TENTATIVE_BIT : 0))
/* Arginfo structures without type information */
#define ZEND_ARG_INFO(pass_by_ref, name) \
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
/* Arginfo structures with simple type information */
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
#define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
/* Arginfo structures with complex type information */
#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
#define ZEND_ARG_OBJ_TYPE_MASK(pass_by_ref, name, class_name, type_mask, default_value) \
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
{ #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
/* Arginfo structures with object type information */
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
#define ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, classname, allow_null, default_value) \
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value },
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), default_value },
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL },
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), NULL },
/* Legacy arginfo structures */
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
{ #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL },
{ #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0, 0)), NULL },
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, is_tentative_return_type) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), \
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0, is_tentative_return_type)), NULL },
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, 0)
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, return_reference, required_num_args, class_name, allow_null, 1)
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2(name, 0, -1, class_name, allow_null, 0)
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, is_tentative_return_type) \
static const zend_internal_arg_info name[] = { \
{ (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 },
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, 0)
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2(name, return_reference, required_num_args, type, 1)
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, is_tentative_return_type) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
{ (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 },
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, 0)
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX2(name, return_reference, required_num_args, class_name, type, 1)
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, is_tentative_return_type) \
static const zend_internal_arg_info name[] = { \
{ (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 },
{ (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 },
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, 0)
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, return_reference, required_num_args, type, allow_null, 1)
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2(name, 0, -1, type, allow_null, 0)
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0, 0)), NULL },
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
#define ZEND_END_ARG_INFO() };
+9
View File
@@ -24,6 +24,7 @@
#include "zend_smart_str.h"
ZEND_API zend_class_entry *zend_ce_attribute;
ZEND_API zend_class_entry *zend_ce_return_type_will_change_attribute;
static HashTable internal_attributes;
@@ -67,6 +68,11 @@ ZEND_METHOD(Attribute, __construct)
ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), flags);
}
ZEND_METHOD(ReturnTypeWillChange, __construct)
{
ZEND_PARSE_PARAMETERS_NONE();
}
static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset)
{
if (attributes) {
@@ -278,6 +284,9 @@ void zend_register_attribute_ce(void)
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_PARAMETER"), ZEND_ATTRIBUTE_TARGET_PARAMETER);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_ALL"), ZEND_ATTRIBUTE_TARGET_ALL);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("IS_REPEATABLE"), ZEND_ATTRIBUTE_IS_REPEATABLE);
zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange();
zend_internal_attribute_register(zend_ce_return_type_will_change_attribute, ZEND_ATTRIBUTE_TARGET_METHOD);
}
void zend_attributes_shutdown(void)
+5
View File
@@ -8,3 +8,8 @@ final class Attribute
public function __construct(int $flags = Attribute::TARGET_ALL) {}
}
final class ReturnTypeWillChange
{
public function __construct() {}
}
+22 -1
View File
@@ -1,12 +1,16 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 0183e750e66999862a7688ecb251017110d06d1f */
* Stub hash: 3fd949e1b9f49666bed3081ed1e8e711acd9f49c */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReturnTypeWillChange___construct, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_METHOD(Attribute, __construct);
ZEND_METHOD(ReturnTypeWillChange, __construct);
static const zend_function_entry class_Attribute_methods[] = {
@@ -14,6 +18,12 @@ static const zend_function_entry class_Attribute_methods[] = {
ZEND_FE_END
};
static const zend_function_entry class_ReturnTypeWillChange_methods[] = {
ZEND_ME(ReturnTypeWillChange, __construct, arginfo_class_ReturnTypeWillChange___construct, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
static zend_class_entry *register_class_Attribute(void)
{
zend_class_entry ce, *class_entry;
@@ -30,3 +40,14 @@ static zend_class_entry *register_class_Attribute(void)
return class_entry;
}
static zend_class_entry *register_class_ReturnTypeWillChange(void)
{
zend_class_entry ce, *class_entry;
INIT_CLASS_ENTRY(ce, "ReturnTypeWillChange", class_ReturnTypeWillChange_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ZEND_ACC_FINAL;
return class_entry;
}
+2 -2
View File
@@ -6476,7 +6476,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
arg_infos->type = zend_compile_typename(
return_type_ast, /* force_allow_null */ 0);
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0, /* is_tentative */ 0);
} else {
arg_infos->type = (zend_type) ZEND_TYPE_INIT_CODE(fallback_return_type, 0, 0);
}
@@ -6606,7 +6606,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type));
}
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic)
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
| (visibility ? _ZEND_IS_PROMOTED_BIT : 0);
ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
if (opcode == ZEND_RECV) {
+4 -1
View File
@@ -983,16 +983,19 @@ ZEND_API zend_string *zend_type_to_string(zend_type type);
#define ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS 1
/* The send mode and is_variadic flag are stored as part of zend_type */
/* The send mode, the is_variadic, the is_promoted, and the is_tentative flags are stored as part of zend_type */
#define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT
#define _ZEND_IS_VARIADIC_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 2))
#define _ZEND_IS_PROMOTED_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 3))
#define _ZEND_IS_TENTATIVE_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 4))
#define ZEND_ARG_SEND_MODE(arg_info) \
((ZEND_TYPE_FULL_MASK((arg_info)->type) >> _ZEND_SEND_MODE_SHIFT) & 3)
#define ZEND_ARG_IS_VARIADIC(arg_info) \
((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_VARIADIC_BIT) != 0)
#define ZEND_ARG_IS_PROMOTED(arg_info) \
((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_PROMOTED_BIT) != 0)
#define ZEND_ARG_TYPE_IS_TENTATIVE(arg_info) \
((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_TENTATIVE_BIT) != 0)
#define ZEND_DIM_IS (1 << 0) /* isset fetch needed for null coalesce */
#define ZEND_DIM_ALTERNATIVE_SYNTAX (1 << 1) /* deprecated curly brace usage */
+1
View File
@@ -1294,6 +1294,7 @@ static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, con
static bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) {
if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
+48 -23
View File
@@ -27,10 +27,21 @@
#include "zend_operators.h"
#include "zend_exceptions.h"
#include "zend_enum.h"
#include "zend_attributes.h"
ZEND_API zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) = NULL;
ZEND_API zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) = NULL;
/* Unresolved means that class declarations that are currently not available are needed to
* determine whether the inheritance is valid or not. At runtime UNRESOLVED should be treated
* as an ERROR. */
typedef enum {
INHERITANCE_UNRESOLVED = -1,
INHERITANCE_ERROR = 0,
INHERITANCE_WARNING = 1,
INHERITANCE_SUCCESS = 2,
} inheritance_status;
static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce);
static void add_compatibility_obligation(
zend_class_entry *ce, const zend_function *child_fn, zend_class_entry *child_scope,
@@ -39,7 +50,12 @@ static void add_property_compatibility_obligation(
zend_class_entry *ce, const zend_property_info *child_prop,
const zend_property_info *parent_prop);
static void zend_type_copy_ctor(zend_type *type, bool persistent) {
static void ZEND_COLD emit_incompatible_method_error(
const zend_function *child, zend_class_entry *child_scope,
const zend_function *parent, zend_class_entry *parent_scope,
inheritance_status status);
static void zend_type_copy_ctor(zend_type *type, zend_bool persistent) {
if (ZEND_TYPE_HAS_LIST(*type)) {
zend_type_list *old_list = ZEND_TYPE_LIST(*type);
size_t size = ZEND_TYPE_LIST_SIZE(old_list->num_types);
@@ -343,16 +359,6 @@ static bool zend_type_permits_self(
return 0;
}
/* Unresolved means that class declarations that are currently not available are needed to
* determine whether the inheritance is valid or not. At runtime UNRESOLVED should be treated
* as an ERROR. */
typedef enum {
INHERITANCE_UNRESOLVED = -1,
INHERITANCE_ERROR = 0,
INHERITANCE_SUCCESS = 1,
} inheritance_status;
static void track_class_dependency(zend_class_entry *ce, zend_string *class_name)
{
HashTable *ht;
@@ -455,7 +461,7 @@ static inheritance_status zend_perform_covariant_class_type_check(
static inheritance_status zend_perform_covariant_type_check(
zend_class_entry *fe_scope, zend_type fe_type,
zend_class_entry *proto_scope, zend_type proto_type) /* {{{ */
zend_class_entry *proto_scope, zend_type proto_type, bool tentative) /* {{{ */
{
ZEND_ASSERT(ZEND_TYPE_IS_SET(fe_type) && ZEND_TYPE_IS_SET(proto_type));
@@ -496,7 +502,7 @@ static inheritance_status zend_perform_covariant_type_check(
if (added_types) {
/* Otherwise adding new types is illegal */
return INHERITANCE_ERROR;
return tentative ? INHERITANCE_WARNING : INHERITANCE_ERROR;
}
}
@@ -522,7 +528,7 @@ static inheritance_status zend_perform_covariant_type_check(
}
if (status == INHERITANCE_ERROR) {
return INHERITANCE_ERROR;
return tentative ? INHERITANCE_WARNING : INHERITANCE_ERROR;
}
if (status != INHERITANCE_SUCCESS) {
all_success = 0;
@@ -570,7 +576,7 @@ static inheritance_status zend_do_perform_arg_type_hint_check(
/* Contravariant type check is performed as a covariant type check with swapped
* argument order. */
return zend_perform_covariant_type_check(
proto_scope, proto_arg_info->type, fe_scope, fe_arg_info->type);
proto_scope, proto_arg_info->type, fe_scope, fe_arg_info->type, 0);
}
/* }}} */
@@ -660,18 +666,25 @@ static inheritance_status zend_do_perform_implementation_check(
/* Check return type compatibility, but only if the prototype already specifies
* a return type. Adding a new return type is always valid. */
if (proto->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
/* Removing a return type is not valid. */
/* Removing a return type is not valid, unless the parent return type is tentative. */
if (!(fe->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
return INHERITANCE_ERROR;
if (ZEND_ARG_TYPE_IS_TENTATIVE(&proto->common.arg_info[-1])) {
if (status == INHERITANCE_SUCCESS) {
emit_incompatible_method_error(fe, fe_scope, proto, proto_scope, INHERITANCE_WARNING);
}
return status;
} else {
return INHERITANCE_ERROR;
}
}
local_status = zend_perform_covariant_type_check(
fe_scope, fe->common.arg_info[-1].type,
proto_scope, proto->common.arg_info[-1].type);
proto_scope, proto->common.arg_info[-1].type, ZEND_ARG_TYPE_IS_TENTATIVE(&proto->common.arg_info[-1]));
if (UNEXPECTED(local_status != INHERITANCE_SUCCESS)) {
if (UNEXPECTED(local_status == INHERITANCE_ERROR)) {
return INHERITANCE_ERROR;
if (UNEXPECTED(local_status == INHERITANCE_ERROR || local_status == INHERITANCE_WARNING)) {
return local_status;
}
ZEND_ASSERT(local_status == INHERITANCE_UNRESOLVED);
status = INHERITANCE_UNRESOLVED;
@@ -854,6 +867,18 @@ static void ZEND_COLD emit_incompatible_method_error(
zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
"Could not check compatibility between %s and %s, because class %s is not available",
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype), ZSTR_VAL(unresolved_class));
} else if (status == INHERITANCE_WARNING) {
zend_attribute *return_type_will_change_attribute = zend_get_attribute_str(
child->common.attributes,
"returntypewillchange",
sizeof("returntypewillchange")-1
);
if (!return_type_will_change_attribute) {
zend_error_at(E_DEPRECATED, NULL, func_lineno(child),
"Declaration of %s should be compatible with %s",
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
}
} else {
zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
"Declaration of %s must be compatible with %s",
@@ -874,7 +899,7 @@ static void perform_delayable_implementation_check(
if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
add_compatibility_obligation(ce, fe, fe_scope, proto, proto_scope);
} else {
ZEND_ASSERT(status == INHERITANCE_ERROR);
ZEND_ASSERT(status == INHERITANCE_ERROR || status == INHERITANCE_WARNING);
emit_incompatible_method_error(fe, fe_scope, proto, proto_scope, status);
}
}
@@ -1048,9 +1073,9 @@ inheritance_status property_types_compatible(
/* Perform a covariant type check in both directions to determined invariance. */
inheritance_status status1 = zend_perform_covariant_type_check(
child_info->ce, child_info->type, parent_info->ce, parent_info->type);
child_info->ce, child_info->type, parent_info->ce, parent_info->type, 0);
inheritance_status status2 = zend_perform_covariant_type_check(
parent_info->ce, parent_info->type, child_info->ce, child_info->type);
parent_info->ce, parent_info->type, child_info->ce, child_info->type, 0);
if (status1 == INHERITANCE_SUCCESS && status2 == INHERITANCE_SUCCESS) {
return INHERITANCE_SUCCESS;
}
+22 -8
View File
@@ -599,16 +599,20 @@ class ReturnInfo {
public $type;
/** @var Type|null */
public $phpDocType;
/** @var bool */
public $tentativeReturnType;
public function __construct(bool $byRef, ?Type $type, ?Type $phpDocType) {
public function __construct(bool $byRef, ?Type $type, ?Type $phpDocType, bool $tentativeReturnType) {
$this->byRef = $byRef;
$this->type = $type;
$this->phpDocType = $phpDocType;
$this->tentativeReturnType = $tentativeReturnType;
}
public function equals(ReturnInfo $other): bool {
return $this->byRef === $other->byRef
&& Type::equals($this->type, $other->type);
&& Type::equals($this->type, $other->type)
&& $this->tentativeReturnType === $other->tentativeReturnType;
}
public function getMethodSynopsisType(): ?Type {
@@ -1431,6 +1435,7 @@ function parseFunctionLike(
$isDeprecated = false;
$verify = true;
$docReturnType = null;
$tentativeReturnType = false;
$docParamTypes = [];
if ($comment) {
@@ -1452,8 +1457,10 @@ function parseFunctionLike(
}
} else if ($tag->name === 'deprecated') {
$isDeprecated = true;
} else if ($tag->name === 'no-verify') {
} else if ($tag->name === 'no-verify') {
$verify = false;
} else if ($tag->name === 'tentative-return-type') {
$tentativeReturnType = true;
} else if ($tag->name === 'return') {
$docReturnType = $tag->getType();
} else if ($tag->name === 'param') {
@@ -1530,7 +1537,8 @@ function parseFunctionLike(
$return = new ReturnInfo(
$func->returnsByRef(),
$returnType ? Type::fromNode($returnType) : null,
$docReturnType ? Type::fromPhpDoc($docReturnType) : null
$docReturnType ? Type::fromPhpDoc($docReturnType) : null,
$tentativeReturnType
);
return new FuncInfo(
@@ -1814,18 +1822,22 @@ function parseStubFile(string $code): FileInfo {
function funcInfoToCode(FuncInfo $funcInfo): string {
$code = '';
$returnType = $funcInfo->return->type;
$isTentativeReturnType = $funcInfo->return->tentativeReturnType;
if ($returnType !== null) {
if (null !== $simpleReturnType = $returnType->tryToSimpleType()) {
if ($simpleReturnType->isBuiltin) {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, %s, %d)\n",
"%s(%s, %d, %d, %s, %d)\n",
$isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$simpleReturnType->toTypeCode(), $returnType->isNullable()
);
} else {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(%s, %d, %d, %s, %d)\n",
"%s(%s, %d, %d, %s, %d)\n",
$isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$simpleReturnType->toEscapedName(), $returnType->isNullable()
@@ -1835,14 +1847,16 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
$arginfoType = $returnType->toArginfoType();
if ($arginfoType->hasClassType()) {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(%s, %d, %d, %s, %s)\n",
"%s(%s, %d, %d, %s, %s)\n",
$isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$arginfoType->toClassTypeString(), $arginfoType->toTypeMask()
);
} else {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(%s, %d, %d, %s)\n",
"%s(%s, %d, %d, %s)\n",
$isTentativeReturnType ? "ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX" : "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$arginfoType->toTypeMask()
+1 -1
View File
@@ -336,7 +336,7 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name
for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) {
bool by_ref = (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) != 0;
f.arg_info[i].type = (zend_type) ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(by_ref, 0));
f.arg_info[i].type = (zend_type) ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(by_ref, 0, 0));
}
f.num_args = bindptr.lpfuncdesc->cParams;
+120 -123
View File
@@ -114,214 +114,211 @@ function date_sunset(
function date_sun_info(int $timestamp, float $latitude, float $longitude): array {}
// NB: Adding return types to methods is a BC break!
// For now only using @return annotations here.
interface DateTimeInterface
{
/** @return string */
public function format(string $format);
/** @tentative-return-type */
public function format(string $format): string;
/** @return DateTimeZone|false */
public function getTimezone();
/** @tentative-return-type */
public function getTimezone(): DateTimeZone|false;
/** @return int */
public function getOffset();
/** @tentative-return-type */
public function getOffset(): int;
/** @return int|false */
public function getTimestamp();
/** @tentative-return-type */
public function getTimestamp(): int|false;
/** @return DateInterval|false */
public function diff(DateTimeInterface $targetObject, bool $absolute = false);
/** @tentative-return-type */
public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval;
/** @return void */
public function __wakeup();
/** @tentative-return-type */
public function __wakeup(): void;
}
class DateTime implements DateTimeInterface
{
public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null) {}
/** @return void */
public function __wakeup() {}
/** @tentative-return-type */
public function __wakeup(): void {}
/** @return DateTime */
public static function __set_state(array $array) {}
/** @tentative-return-type */
public static function __set_state(array $array): DateTime {}
/** @return DateTime */
public static function createFromImmutable(DateTimeImmutable $object) {}
/** @tentative-return-type */
public static function createFromImmutable(DateTimeImmutable $object): DateTime {}
public static function createFromInterface(DateTimeInterface $object): DateTime {}
/**
* @return DateTime|false
* @tentative-return-type
* @alias date_create_from_format
*/
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) {}
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTime|false {}
/**
* @return array|false
* @tentative-return-type
* @alias date_get_last_errors
*/
public static function getLastErrors() {}
public static function getLastErrors(): array|false {}
/**
* @return string
* @tentative-return-type
* @alias date_format
*/
public function format(string $format) {}
public function format(string $format): string {}
/**
* @return DateTime|false
* @tentative-return-type
* @alias date_modify
*/
public function modify(string $modifier) {}
public function modify(string $modifier): DateTime|false {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_add
*/
public function add(DateInterval $interval) {}
public function add(DateInterval $interval): DateTime {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_sub
*/
public function sub(DateInterval $interval) {}
public function sub(DateInterval $interval): DateTime {}
/**
* @return DateTimeZone|false
* @tentative-return-type
* @alias date_timezone_get
*/
public function getTimezone() {}
public function getTimezone(): DateTimeZone|false {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_timezone_set
*/
public function setTimezone(DateTimeZone $timezone) {}
public function setTimezone(DateTimeZone $timezone): DateTime {}
/**
* @return int
* @tentative-return-type
* @alias date_offset_get
*/
public function getOffset() {}
public function getOffset(): int {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_time_set
*/
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0) {}
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTime {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_date_set
*/
public function setDate(int $year, int $month, int $day) {}
public function setDate(int $year, int $month, int $day): DateTime {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_isodate_set
*/
public function setISODate(int $year, int $week, int $dayOfWeek = 1) {}
public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTime {}
/**
* @return DateTime
* @tentative-return-type
* @alias date_timestamp_set
*/
public function setTimestamp(int $timestamp) {}
public function setTimestamp(int $timestamp): DateTime {}
/**
* @return int
* @tentative-return-type
* @alias date_timestamp_get
*/
public function getTimestamp() {}
public function getTimestamp(): int {}
/**
* @return DateInterval
* @tentative-return-type
* @alias date_diff
*/
public function diff(DateTimeInterface $targetObject, bool $absolute = false) {}
public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval {}
}
class DateTimeImmutable implements DateTimeInterface
{
public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null) {}
/** @return void */
public function __wakeup() {}
/** @tentative-return-type */
public function __wakeup(): void {}
/** @return DateTimeImmutable */
public static function __set_state(array $array) {}
/** @tentative-return-type */
public static function __set_state(array $array): DateTimeImmutable {}
/**
* @return DateTimeImmutable|false
* @tentative-return-type
* @alias date_create_immutable_from_format
*/
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) {}
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false {}
/**
* @return array|false
* @tentative-return-type
* @alias date_get_last_errors
*/
public static function getLastErrors() {}
public static function getLastErrors(): array|false {}
/**
* @return string
* @tentative-return-type
* @alias date_format
*/
public function format(string $format) {}
public function format(string $format): string {}
/**
* @return DateTimeZone|false
* @tentative-return-type
* @alias date_timezone_get
*/
public function getTimezone() {}
public function getTimezone(): DateTimeZone|false {}
/**
* @return int
* @tentative-return-type
* @alias date_offset_get
*/
public function getOffset() {}
public function getOffset(): int {}
/**
* @return int
* @tentative-return-type
* @alias date_timestamp_get
*/
public function getTimestamp() {}
public function getTimestamp(): int {}
/**
* @return DateInterval
* @tentative-return-type
* @alias date_diff
*/
public function diff(DateTimeInterface $targetObject, bool $absolute = false) {}
public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval {}
/** @return DateTimeImmutable|false */
public function modify(string $modifier) {}
/** @tentative-return-type */
public function modify(string $modifier): DateTimeImmutable|false {}
/** @return DateTimeImmutable */
public function add(DateInterval $interval) {}
/** @tentative-return-type */
public function add(DateInterval $interval): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function sub(DateInterval $interval) {}
/** @tentative-return-type */
public function sub(DateInterval $interval): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function setTimezone(DateTimeZone $timezone) {}
/** @tentative-return-type */
public function setTimezone(DateTimeZone $timezone): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0) {}
/** @tentative-return-type */
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function setDate(int $year, int $month, int $day) {}
/** @tentative-return-type */
public function setDate(int $year, int $month, int $day): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function setISODate(int $year, int $week, int $dayOfWeek = 1) {}
/** @tentative-return-type */
public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTimeImmutable {}
/** @return DateTimeImmutable */
public function setTimestamp(int $timestamp) {}
/** @tentative-return-type */
public function setTimestamp(int $timestamp): DateTimeImmutable {}
/** @return DateTimeImmutable */
public static function createFromMutable(DateTime $object) {}
/** @tentative-return-type */
public static function createFromMutable(DateTime $object): DateTimeImmutable {}
public static function createFromInterface(DateTimeInterface $object): DateTimeImmutable {}
}
@@ -331,46 +328,46 @@ class DateTimeZone
public function __construct(string $timezone) {}
/**
* @return string
* @tentative-return-type
* @alias timezone_name_get
*/
public function getName() {}
public function getName(): string {}
/**
* @return int
* @tentative-return-type
* @alias timezone_offset_get
*/
public function getOffset(DateTimeInterface $datetime) {}
public function getOffset(DateTimeInterface $datetime): int {}
/**
* @return array|false
* @tentative-return-type
* @alias timezone_transitions_get
*/
public function getTransitions(int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX) {}
public function getTransitions(int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX): array|false {}
/**
* @return array|false
* @tentative-return-type
* @alias timezone_location_get
*/
public function getLocation() {}
public function getLocation(): array|false {}
/**
* @return array
* @tentative-return-type
* @alias timezone_abbreviations_list
*/
public static function listAbbreviations() {}
public static function listAbbreviations(): array {}
/**
* @return array
* @tentative-return-type
* @alias timezone_identifiers_list
*/
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null) {}
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {}
/** @return void */
public function __wakeup() {}
/** @tentative-return-type */
public function __wakeup(): void {}
/** @return DateTimeZone */
public static function __set_state(array $array) {}
/** @tentative-return-type */
public static function __set_state(array $array): DateTimeZone {}
}
class DateInterval
@@ -378,22 +375,22 @@ class DateInterval
public function __construct(string $duration) {}
/**
* @return DateInterval|false
* @tentative-return-type
* @alias date_interval_create_from_date_string
*/
public static function createFromDateString(string $datetime) {}
public static function createFromDateString(string $datetime): DateInterval|false {}
/**
* @return string
* @tentative-return-type
* @alias date_interval_format
*/
public function format(string $format) {}
public function format(string $format): string {}
/** @return void */
public function __wakeup() {}
/** @tentative-return-type */
public function __wakeup(): void {}
/** @return DateInterval */
public static function __set_state(array $array) {}
/** @tentative-return-type */
public static function __set_state(array $array): DateInterval {}
}
class DatePeriod implements IteratorAggregate
@@ -406,23 +403,23 @@ class DatePeriod implements IteratorAggregate
*/
public function __construct($start, $interval = UNKNOWN, $end = UNKNOWN, $options = UNKNOWN) {}
/** @return DateTimeInterface */
public function getStartDate() {}
/** @tentative-return-type */
public function getStartDate(): DateTimeInterface {}
/** @return DateTimeInterface|null */
public function getEndDate() {}
/** @tentative-return-type */
public function getEndDate(): ?DateTimeInterface {}
/** @return DateInterval */
public function getDateInterval() {}
/** @tentative-return-type */
public function getDateInterval(): DateInterval {}
/** @return int|null */
public function getRecurrences() {}
/** @tentative-return-type */
public function getRecurrences(): ?int {}
/** @return void */
public function __wakeup() {}
/** @tentative-return-type */
public function __wakeup(): void {}
/** @return DatePeriod */
public static function __set_state(array $array) {}
/** @tentative-return-type */
public static function __set_state(array $array): DatePeriod {}
public function getIterator(): Iterator {}
}
+96 -53
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 108136459e578cc699cffcb84d3335a11f8d5c9d */
* Stub hash: e8bc76a5db3a225746daffe29c0b8404cf971452 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
@@ -225,36 +225,39 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_date_sun_info, 0, 3, IS_ARRAY, 0
ZEND_ARG_TYPE_INFO(0, longitude, IS_DOUBLE, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeInterface_format, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface_format, 0, 1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeInterface_getTimezone, 0, 0, 0)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTimeInterface_getTimezone, 0, 0, DateTimeZone, MAY_BE_FALSE)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeInterface_getOffset arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface_getOffset, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeInterface_getTimestamp arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DateTimeInterface_getTimestamp, 0, 0, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeInterface_diff, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeInterface_diff, 0, 1, DateInterval, 0)
ZEND_ARG_OBJ_INFO(0, targetObject, DateTimeInterface, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, absolute, _IS_BOOL, 0, "false")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeInterface___wakeup arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface___wakeup, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, datetime, IS_STRING, 0, "\"now\"")
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTime___wakeup arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTime___wakeup arginfo_class_DateTimeInterface___wakeup
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime___set_state, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime___set_state, 0, 1, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_createFromImmutable, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_createFromImmutable, 0, 1, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeImmutable, 0)
ZEND_END_ARG_INFO()
@@ -262,21 +265,22 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_createFromInterfac
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_createFromFormat, 0, 0, 2)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTime_createFromFormat, 0, 2, DateTime, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTime_getLastErrors arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DateTime_getLastErrors, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTime_format arginfo_class_DateTimeInterface_format
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_modify, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTime_modify, 0, 1, DateTime, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, modifier, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_add, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_add, 0, 1, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, interval, DateInterval, 0)
ZEND_END_ARG_INFO()
@@ -284,76 +288,103 @@ ZEND_END_ARG_INFO()
#define arginfo_class_DateTime_getTimezone arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_setTimezone, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_setTimezone, 0, 1, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, timezone, DateTimeZone, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTime_getOffset arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTime_getOffset arginfo_class_DateTimeInterface_getOffset
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_setTime, 0, 0, 2)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_setTime, 0, 2, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, hour, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, minute, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, second, IS_LONG, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, microsecond, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_setDate, 0, 0, 3)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_setDate, 0, 3, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, month, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, day, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_setISODate, 0, 0, 2)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_setISODate, 0, 2, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, week, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dayOfWeek, IS_LONG, 0, "1")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime_setTimestamp, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_setTimestamp, 0, 1, DateTime, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTime_getTimestamp arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTime_getTimestamp arginfo_class_DateTimeInterface_getOffset
#define arginfo_class_DateTime_diff arginfo_class_DateTimeInterface_diff
#define arginfo_class_DateTimeImmutable___construct arginfo_class_DateTime___construct
#define arginfo_class_DateTimeImmutable___wakeup arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeImmutable___wakeup arginfo_class_DateTimeInterface___wakeup
#define arginfo_class_DateTimeImmutable___set_state arginfo_class_DateTime___set_state
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable___set_state, 0, 1, DateTimeImmutable, 0)
ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_createFromFormat arginfo_class_DateTime_createFromFormat
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTimeImmutable_createFromFormat, 0, 2, DateTimeImmutable, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, format, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_getLastErrors arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeImmutable_getLastErrors arginfo_class_DateTime_getLastErrors
#define arginfo_class_DateTimeImmutable_format arginfo_class_DateTimeInterface_format
#define arginfo_class_DateTimeImmutable_getTimezone arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeImmutable_getOffset arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeImmutable_getOffset arginfo_class_DateTimeInterface_getOffset
#define arginfo_class_DateTimeImmutable_getTimestamp arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeImmutable_getTimestamp arginfo_class_DateTimeInterface_getOffset
#define arginfo_class_DateTimeImmutable_diff arginfo_class_DateTimeInterface_diff
#define arginfo_class_DateTimeImmutable_modify arginfo_class_DateTime_modify
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateTimeImmutable_modify, 0, 1, DateTimeImmutable, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, modifier, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_add arginfo_class_DateTime_add
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_add, 0, 1, DateTimeImmutable, 0)
ZEND_ARG_OBJ_INFO(0, interval, DateInterval, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_sub arginfo_class_DateTime_add
#define arginfo_class_DateTimeImmutable_sub arginfo_class_DateTimeImmutable_add
#define arginfo_class_DateTimeImmutable_setTimezone arginfo_class_DateTime_setTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_setTimezone, 0, 1, DateTimeImmutable, 0)
ZEND_ARG_OBJ_INFO(0, timezone, DateTimeZone, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_setTime arginfo_class_DateTime_setTime
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_setTime, 0, 2, DateTimeImmutable, 0)
ZEND_ARG_TYPE_INFO(0, hour, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, minute, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, second, IS_LONG, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, microsecond, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_setDate arginfo_class_DateTime_setDate
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_setDate, 0, 3, DateTimeImmutable, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, month, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, day, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_setISODate arginfo_class_DateTime_setISODate
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_setISODate, 0, 2, DateTimeImmutable, 0)
ZEND_ARG_TYPE_INFO(0, year, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, week, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dayOfWeek, IS_LONG, 0, "1")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeImmutable_setTimestamp arginfo_class_DateTime_setTimestamp
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_setTimestamp, 0, 1, DateTimeImmutable, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeImmutable_createFromMutable, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_createFromMutable, 0, 1, DateTimeImmutable, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_END_ARG_INFO()
@@ -365,43 +396,49 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeZone___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, timezone, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeZone_getName arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_getName, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeZone_getOffset, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_getOffset, 0, 1, IS_LONG, 0)
ZEND_ARG_OBJ_INFO(0, datetime, DateTimeInterface, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeZone_getTransitions, 0, 0, 0)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_DateTimeZone_getTransitions, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timestampBegin, IS_LONG, 0, "PHP_INT_MIN")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timestampEnd, IS_LONG, 0, "PHP_INT_MAX")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeZone_getLocation arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeZone_getLocation arginfo_class_DateTime_getLastErrors
#define arginfo_class_DateTimeZone_listAbbreviations arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_listAbbreviations, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTimeZone_listIdentifiers, 0, 0, 0)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_listIdentifiers, 0, 0, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timezoneGroup, IS_LONG, 0, "DateTimeZone::ALL")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface___wakeup
#define arginfo_class_DateTimeZone___set_state arginfo_class_DateTime___set_state
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeZone___set_state, 0, 1, DateTimeZone, 0)
ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateInterval___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, duration, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateInterval_createFromDateString, 0, 0, 1)
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_DateInterval_createFromDateString, 0, 1, DateInterval, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DateInterval_format arginfo_class_DateTimeInterface_format
#define arginfo_class_DateInterval___wakeup arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DateInterval___wakeup arginfo_class_DateTimeInterface___wakeup
#define arginfo_class_DateInterval___set_state arginfo_class_DateTime___set_state
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateInterval___set_state, 0, 1, DateInterval, 0)
ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DatePeriod___construct, 0, 0, 1)
ZEND_ARG_INFO(0, start)
@@ -410,17 +447,23 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DatePeriod___construct, 0, 0, 1)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
#define arginfo_class_DatePeriod_getStartDate arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod_getStartDate, 0, 0, DateTimeInterface, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DatePeriod_getEndDate arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod_getEndDate, 0, 0, DateTimeInterface, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_DatePeriod_getDateInterval arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod_getDateInterval, 0, 0, DateInterval, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DatePeriod_getRecurrences arginfo_class_DateTimeInterface_getTimezone
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DatePeriod_getRecurrences, 0, 0, IS_LONG, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_DatePeriod___wakeup arginfo_class_DateTimeInterface_getTimezone
#define arginfo_class_DatePeriod___wakeup arginfo_class_DateTimeInterface___wakeup
#define arginfo_class_DatePeriod___set_state arginfo_class_DateTime___set_state
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod___set_state, 0, 1, DatePeriod, 0)
ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod_getIterator, 0, 0, Iterator, 0)
ZEND_END_ARG_INFO()
+1 -1
View File
@@ -9,7 +9,7 @@ echo "*** Testing new DateTime() : with user format() method ***\n";
class DateTimeExt extends DateTime
{
public function format($format = "F j, Y, g:i:s a")
public function format($format = "F j, Y, g:i:s a"): string
{
return parent::format($format);
}
+1 -1
View File
@@ -6,7 +6,7 @@ error_reporting=-1
<?php namespace melt\core;
class DateTime extends \DateTime {
public static function createFromFormat($format, $time, \DateTimeZone $timezone = null) {
public static function createFromFormat($format, $time, \DateTimeZone $timezone = null): DateTime|false {
return new DateTime(parent::createFromFormat($format, $time, $timezone));
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ $s2 = 'O:3:"Foo":3:{s:4:"date";s:20:"10007-06-07 03:51:49";s:13:"timezone_type";
global $foo;
class Foo extends DateTime {
function __wakeup() {
function __wakeup(): void {
global $foo;
$foo = $this;
parent::__wakeup();
+1 -1
View File
@@ -9,7 +9,7 @@ $s2 = 'O:3:"Foo":3:{s:4:"date";s:19:"0000-00-00 00:00:00";s:13:"timezone_type";i
global $foo;
class Foo extends DateTime {
function __wakeup() {
function __wakeup(): void {
global $foo;
$foo = $this;
parent::__wakeup();
+40 -4
View File
@@ -849,8 +849,8 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent
}
_function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
smart_str_free(&param_indent);
if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
smart_str_append_printf(str, " %s- Return [ ", indent);
if ((fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
smart_str_append_printf(str, " %s- %s [ ", indent, ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]) ? "Tentative return" : "Return");
if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) {
zend_string *type_str = zend_type_to_string(fptr->common.arg_info[-1].type);
smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str));
@@ -3449,7 +3449,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType)
GET_REFLECTION_OBJECT_PTR(fptr);
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
RETVAL_BOOL((fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
}
/* }}} */
@@ -3465,7 +3465,43 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
GET_REFLECTION_OBJECT_PTR(fptr);
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
RETURN_NULL();
}
reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
}
/* }}} */
/* {{{ Return whether the function has a return type */
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType)
{
reflection_object *intern;
zend_function *fptr;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(fptr);
RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]));
}
/* }}} */
/* {{{ Returns the return type associated with the function */
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType)
{
reflection_object *intern;
zend_function *fptr;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(fptr);
if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || !ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1])) {
RETURN_NULL();
}
+4
View File
@@ -98,6 +98,10 @@ abstract class ReflectionFunctionAbstract implements Reflector
/** @return ReflectionType|null */
public function getReturnType() {}
public function hasTentativeReturnType(): bool {}
public function getTentativeReturnType(): ?ReflectionType {}
/** @return ReflectionAttribute[] */
public function getAttributes(?string $name = null, int $flags = 0): array {}
}
+19 -11
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 47ac64b027cdeb0e9996147277f79fa9d6b876bd */
* Stub hash: 0b2b52d4f891a594ccfcbcc0edeec97a9e0f80e6 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
@@ -59,6 +59,12 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionFunctionAbstract_getReturnType arginfo_class_ReflectionFunctionAbstract_inNamespace
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType, 0, 0, ReflectionType, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunctionAbstract_getAttributes, 0, 0, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, name, IS_STRING, 1, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0")
@@ -218,8 +224,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionClass_isTrait arginfo_class_ReflectionFunctionAbstract_inNamespace
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionClass_isEnum, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionClass_isEnum arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionClass_isAbstract arginfo_class_ReflectionFunctionAbstract_inNamespace
@@ -311,7 +316,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract_inNamespace
#define arginfo_class_ReflectionProperty_isPromoted arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionProperty_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionProperty_getModifiers arginfo_class_ReflectionFunctionAbstract_inNamespace
@@ -325,7 +330,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_hasType arginfo_class_ReflectionFunctionAbstract_inNamespace
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionProperty_hasDefaultValue arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionProperty_getDefaultValue arginfo_class_ReflectionFunctionAbstract_inNamespace
@@ -358,7 +363,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionClassConstant_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
#define arginfo_class_ReflectionClassConstant_isEnumCase arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionClassConstant_isEnumCase arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionParameter___clone arginfo_class_ReflectionFunctionAbstract___clone
@@ -405,7 +410,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionParameter_isVariadic arginfo_class_ReflectionFunctionAbstract_inNamespace
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionParameter_isPromoted arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionParameter_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes
@@ -482,7 +487,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_getTarget, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionAttribute_isRepeated arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
#define arginfo_class_ReflectionAttribute_getArguments arginfo_class_ReflectionUnionType_getTypes
@@ -505,10 +510,9 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionEnum_getCases arginfo_class_ReflectionUnionType_getTypes
#define arginfo_class_ReflectionEnum_isBacked arginfo_class_ReflectionClass_isEnum
#define arginfo_class_ReflectionEnum_isBacked arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionEnum_getBackingType, 0, 0, ReflectionType, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionEnum_getBackingType arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType
#define arginfo_class_ReflectionEnumUnitCase___construct arginfo_class_ReflectionClassConstant___construct
@@ -569,6 +573,8 @@ ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables);
ZEND_METHOD(ReflectionFunctionAbstract, returnsReference);
ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType);
ZEND_METHOD(ReflectionFunctionAbstract, getReturnType);
ZEND_METHOD(ReflectionFunctionAbstract, hasTentativeReturnType);
ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType);
ZEND_METHOD(ReflectionFunctionAbstract, getAttributes);
ZEND_METHOD(ReflectionFunction, __construct);
ZEND_METHOD(ReflectionFunction, __toString);
@@ -805,6 +811,8 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = {
ZEND_ME(ReflectionFunctionAbstract, returnsReference, arginfo_class_ReflectionFunctionAbstract_returnsReference, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunctionAbstract, hasReturnType, arginfo_class_ReflectionFunctionAbstract_hasReturnType, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunctionAbstract, getReturnType, arginfo_class_ReflectionFunctionAbstract_getReturnType, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunctionAbstract, hasTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunctionAbstract, getTentativeReturnType, arginfo_class_ReflectionFunctionAbstract_getTentativeReturnType, ZEND_ACC_PUBLIC)
ZEND_ME(ReflectionFunctionAbstract, getAttributes, arginfo_class_ReflectionFunctionAbstract_getAttributes, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
@@ -0,0 +1,62 @@
--TEST--
ReflectionMethod returns tentative return type information correctly
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
#[ReturnTypeWillChange]
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): string
{
return "";
}
}
$methodInfo = new ReflectionMethod(DateTimeZone::class, 'listIdentifiers');
var_dump($methodInfo->hasReturnType());
var_dump($methodInfo->hasTentativeReturnType());
var_dump($methodInfo->getReturnType());
var_dump((string) $methodInfo->getTentativeReturnType());
var_dump((string) $methodInfo);
echo "\n";
$methodInfo = new ReflectionMethod(MyDateTimeZone::class, 'listIdentifiers');
var_dump($methodInfo->hasReturnType());
var_dump($methodInfo->hasTentativeReturnType());
var_dump((string) $methodInfo->getReturnType());
var_dump($methodInfo->getTentativeReturnType());
var_dump((string) $methodInfo);
echo "\n";
?>
--EXPECTF--
bool(false)
bool(true)
NULL
string(5) "array"
string(%d) "Method [ <internal:date> static public method listIdentifiers ] {
- Parameters [2] {
Parameter #0 [ <optional> int $timezoneGroup = DateTimeZone::ALL ]
Parameter #1 [ <optional> ?string $countryCode = null ]
}
- Tentative return [ array ]
}
"
bool(true)
bool(false)
string(6) "string"
NULL
string(%d) "Method [ <user, overwrites DateTimeZone, prototype DateTimeZone> static public method listIdentifiers ] {
@@ %s
- Parameters [2] {
Parameter #0 [ <optional> int $timezoneGroup = %d ]
Parameter #1 [ <optional> ?string $countryCode = NULL ]
}
- Return [ string ]
}
"