Skip to content

Store parameter default values in arginfo #4832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ PHP NEWS
. Fixed bug #69180 (Reflection does not honor trait conflict resolution /
method aliasing). (Nikita)
. Fixed bug #74939 (Nested traits' aliased methods are lowercased). (Nikita)
. Implement ReflectionParameter::getDefaultValueString (kocsismate)

- Session:
. Fixed bug #78624 (session_gc return value for user defined session
Expand Down
8 changes: 8 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,14 @@ PHP 8.0 UPGRADE NOTES
result will include a nullability indicator for nullable types. The format
of the return value is not stable and may change between PHP versions.
. Reflection export() methods have been removed.
. The following methods can now return information about default values of
parameters of internal functions:
ReflectionParameter::isDefaultValueAvailable()
ReflectionParameter::getDefaultValue()
ReflectionParameter::isDefaultValueConstant()
ReflectionParameter::getDefaultValueConstantName()
. The ReflectionParameter::isDefaultValueConstant() and
ReflectionParameter::getDefaultValueConstantName() methods have been deprecated.

- Socket:
. The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/argument_restriction_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ class Sub extends Base {
}
?>
--EXPECTF--
Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_001.php on line %d
Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'lllllllllllllllllllllllllllllllllllllllllllllllllll') in %sargument_restriction_001.php on line %d
2 changes: 1 addition & 1 deletion Zend/tests/argument_restriction_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ class Sub extends Base {
}
?>
--EXPECTF--
Fatal error: Declaration of Sub::test() must be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_003.php on line %d
Fatal error: Declaration of Sub::test() must be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'lllllllllllllllllllllllllllllllllllllllllllllllllll') in %sargument_restriction_003.php on line %d
2 changes: 1 addition & 1 deletion Zend/tests/argument_restriction_006.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ class Sub extends Base {
}
?>
--EXPECTF--
Fatal error: Declaration of Sub::test($foo, $extra) must be compatible with Base::test($foo, $extra = Array) in %sargument_restriction_006.php on line %d
Fatal error: Declaration of Sub::test($foo, $extra) must be compatible with Base::test($foo, $extra = ['test']) in %sargument_restriction_006.php on line %d
2 changes: 1 addition & 1 deletion Zend/tests/bug64988.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ $o = new Smooth1();
echo "okey";
?>
--EXPECTF--
Fatal error: Declaration of Smooth1::insert(array $data) must be compatible with Noisy1::insert(array $data, $option1 = NULL) in %sbug64988.php on line 17
Fatal error: Declaration of Smooth1::insert(array $data) must be compatible with Noisy1::insert(array $data, $option1 = Null) in %sbug64988.php on line 17
2 changes: 1 addition & 1 deletion Zend/tests/bug70957.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ class B extends Foo
}
?>
--EXPECTF--
Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = 'Foo') in %sbug70957.php on line %d
Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = self::class) in %sbug70957.php on line %d
2 changes: 1 addition & 1 deletion Zend/tests/bug71428.1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ class B extends A {
public function m(array $a = []) {}
}
--EXPECTF--
Fatal error: Declaration of B::m(array $a = Array) must be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 6
Fatal error: Declaration of B::m(array $a = []) must be compatible with A::m(?array $a = null) in %sbug71428.1.php on line 6
2 changes: 1 addition & 1 deletion Zend/tests/bug72119.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class Hello implements Foo {
echo "OK\n";
?>
--EXPECTF--
Fatal error: Declaration of Hello::bar(array $baz = Array) must be compatible with Foo::bar(?array $baz = NULL) in %s on line %d
Fatal error: Declaration of Hello::bar(array $baz = []) must be compatible with Foo::bar(?array $baz = null) in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/bug73987.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class B extends A {

?>
--EXPECTF--
Fatal error: Declaration of B::example($a, $b, $c = NULL) must be compatible with A::example($a, $b = NULL, $c = NULL) in %s
Fatal error: Declaration of B::example($a, $b, $c = null) must be compatible with A::example($a, $b = null, $c = null) in %s
2 changes: 1 addition & 1 deletion Zend/tests/bug73987_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ class C extends B {

?>
--EXPECTF--
Fatal error: Declaration of C::example($a, $b, $c = NULL) must be compatible with B::example($a, $b = NULL, $c = NULL) in %s
Fatal error: Declaration of C::example($a, $b, $c = null) must be compatible with B::example($a, $b = null, $c = null) in %s
4 changes: 2 additions & 2 deletions Zend/tests/closures/closure_from_callable_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ $foo = new SubFoo;
$fn = $foo->getSelfColonParentPublicInstanceMethod();
echo $fn(" OK".PHP_EOL);

echo 'Access proteced instance method of parent object through "self::" to parent method';
echo 'Access protected instance method of parent object through "self::" to parent method';
$foo = new SubFoo;
$fn = $foo->getSelfColonParentProtectedInstanceMethod();
echo $fn(" OK".PHP_EOL);
Expand Down Expand Up @@ -114,6 +114,6 @@ Subclass closure over parent class static protected method OK
Access public instance method of parent object through "parent::" OK
Access public instance method of self object through "self::" OK
Access public instance method of parent object through "self::" to parent method OK
Access proteced instance method of parent object through "self::" to parent method OK
Access protected instance method of parent object through "self::" to parent method OK
MagicCall __call instance method __call,nonExistentMethod, OK
MagicCall __callStatic static method __callStatic,nonExistentMethod, OK
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
The default value is a class constant in the parent class method's signature.
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
public static function listIdentifiers()
{
}
}
--EXPECTF--
Fatal error: Declaration of MyDateTimeZone::listIdentifiers() must be compatible with DateTimeZone::listIdentifiers(int $what = DateTimeZone::ALL, ?string $country = null) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
The default value is a constant in the parent class method's signature.
--FILE--
<?php
class MyDateTimeZone extends DateTimeZone
{
public function getTransitions()
{
}
}
--EXPECTF--
Fatal error: Declaration of MyDateTimeZone::getTransitions() must be compatible with DateTimeZone::getTransitions(int $timestamp_begin = PHP_INT_MIN, int $timestamp_end = PHP_INT_MAX) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
The default value is false in the parent class method's signature.
--FILE--
<?php

interface MyDateTimeInterface extends DateTimeInterface
{
public function diff();
}
--EXPECTF--
Fatal error: Declaration of MyDateTimeInterface::diff() must be compatible with DateTimeInterface::diff(DateTimeInterface $object, bool $absolute = false) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
The default value is an integer in the parent class method's signature.
--FILE--
<?php
class MyDateTime extends DateTime
{
public function setTime(int $hour, int $minute, int $second = 0, bool $microseconds = false)
{
}
}
--EXPECTF--
Fatal error: Declaration of MyDateTime::setTime(int $hour, int $minute, int $second = 0, bool $microseconds = false) must be compatible with DateTime::setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
The default value is null in the parent class method's signature.
--FILE--
<?php
class MyDateTime extends DateTime
{
public static function createFromFormat()
{
}
}
--EXPECTF--
Fatal error: Declaration of MyDateTime::createFromFormat() must be compatible with DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = null) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
The default value is a constant in the parent class method's signature.
--FILE--
<?php

use Foo\Bar;

class A
{
public function foo(
$param1 = \Foo\Bar::CONSTANT,
$param2 = Foo\Bar::CONSTANT,
$param3 = Bar::CONSTANT
) {
}
}

class B extends A
{
public function foo()
{
}
}
--EXPECTF--
Fatal error: Declaration of B::foo() must be compatible with A::foo($param1 = \Foo\Bar::CONSTANT, $param2 = Foo\Bar::CONSTANT, $param3 = Bar::CONSTANT) in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
The default value is a constant in the parent class method's signature.
--FILE--
<?php

use const Foo\CONSTANT;

class A
{
public function foo(
$param1 = \Foo\CONSTANT,
$param2 = Foo\CONSTANT,
$param3 = CONSTANT
) {
}
}

class B extends A
{
public function foo()
{
}
}
--EXPECTF--
Fatal error: Declaration of B::foo() must be compatible with A::foo($param1 = \Foo\CONSTANT, $param2 = Foo\CONSTANT, $param3 = CONSTANT) in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/type_declarations/variance/internal_parent.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ class Test extends DateTime {

?>
--EXPECTF--
Fatal error: Could not check compatibility between Test::createFromFormat($format, $time, ?Wrong $timezone = NULL) and DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = NULL), because class Wrong is not available in %s on line %d
Fatal error: Could not check compatibility between Test::createFromFormat($format, $time, ?Wrong $timezone = null) and DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = null), because class Wrong is not available in %s on line %d
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ class MySQL implements DB {

?>
--EXPECTF--
Fatal error: Declaration of MySQL::query($query, ?int $extraParam = NULL, string ...$params) must be compatible with DB::query($query, string ...$params) in %s on line %d
Fatal error: Declaration of MySQL::query($query, ?int $extraParam = null, string ...$params) must be compatible with DB::query($query, string ...$params) in %s on line %d
49 changes: 30 additions & 19 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,50 +105,61 @@ typedef struct _zend_fcall_info_cache {
#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \
(((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_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))},
#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)) },
#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)) },
#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)) },
#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)) },
#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask) \
{ #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) },
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 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 },
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) },
{ #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), 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 },
#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 },
#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)) },
{ #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), 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 },
/* 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 },
#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 },
#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)) },
{ #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), 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 },
#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 },

#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
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)) },
ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },

#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)

#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, 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)) },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },

#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, 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)) },
{ (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 },

#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)) },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
#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)

#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)) },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL },
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
#define ZEND_END_ARG_INFO() };
Expand Down
Loading