From 0248ab932c8e3c62ade52c686f345a0942d9efeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Fri, 15 Dec 2023 15:43:23 +0100 Subject: [PATCH] Deprecate implicit nullable parameter types RFC: https://wiki.php.net/rfc/deprecate-implicitly-nullable-types Co-authored-by: Gina Peter Banyard --- UPGRADING | 4 + Zend/tests/bug63635.phpt | 2 +- Zend/tests/bug71428.1.phpt | 2 +- Zend/tests/bug71428.3.phpt | 2 + Zend/tests/bug72119.phpt | 2 +- Zend/tests/gh11488.phpt | 2 + Zend/tests/ns_070.phpt | 2 +- Zend/tests/ns_071.phpt | 2 +- Zend/tests/ns_072.phpt | 2 +- Zend/tests/ns_073.phpt | 1 + Zend/tests/ns_074.phpt | 2 +- Zend/tests/required_param_after_optional.phpt | 4 + Zend/tests/traits/bug60717.phpt | 7 +- .../tests/type_declarations/callable_003.phpt | 3 +- .../implicit_nullable_intersection_type.phpt | 3 +- ...icit_nullable_intersection_type_error.phpt | 1 + .../iterable/iterable_002.phpt | 2 + ...false_standalone_implicit_nullability.phpt | 3 +- .../true_standalone_implicit_nullability.phpt | 3 +- .../type_declarations/nullable_null.phpt | 3 +- Zend/tests/type_declarations/scalar_none.phpt | 8 +- Zend/tests/type_declarations/scalar_null.phpt | 8 +- .../unresolvable_inheritance_check_param.phpt | 2 +- .../adding_additional_optional_parameter.phpt | 4 +- ...g_additional_optional_parameter_error.phpt | 2 +- Zend/zend_compile.c | 5 + ext/date/tests/DateTime_extends_basic2.phpt | 2 +- ext/date/tests/bug55407.phpt | 2 +- ext/opcache/tests/bug73746.phpt | 2 +- ext/opcache/tests/bug74442.phpt | 4 +- ext/opcache/tests/invalid_array_key_type.phpt | 2 +- ext/opcache/tests/jit/cast_001.phpt | 2 +- ext/opcache/tests/jit/send_var_ex_002.phpt | 2 +- ext/opcache/tests/opt/assign_op_002.phpt | 2 +- ext/pdo_pgsql/tests/bug72294.phpt | 2 +- .../tests/ReflectionClass_export_basic1.phpt | 3 +- ext/reflection/tests/bug62715.phpt | 4 +- ext/reflection/tests/parameters_002.phpt | 3 +- .../tests/types/ReflectionType_001.phpt | 3 +- ...intersection_type_implicitly_nullable.phpt | 3 +- ext/spl/tests/bug65328.phpt | 6 +- sapi/fpm/tests/logreader.inc | 6 +- sapi/fpm/tests/logtool.inc | 50 ++++----- sapi/fpm/tests/tester.inc | 106 +++++++++--------- .../phpdbg_get_executable_stream_wrapper.phpt | 2 +- tests/classes/type_hinting_003.phpt | 1 + tests/classes/type_hinting_004.phpt | 5 + tests/lang/type_hints_002.phpt | 3 +- 48 files changed, 170 insertions(+), 126 deletions(-) diff --git a/UPGRADING b/UPGRADING index 09b277339ed3c..1e5b6caa3cd42 100644 --- a/UPGRADING +++ b/UPGRADING @@ -268,6 +268,10 @@ PHP 8.4 UPGRADE NOTES 4. Deprecated Functionality ======================================== +- Core: + . Implicitly nullable parameter types are now deprecated. + RFC: https://wiki.php.net/rfc/deprecate-implicitly-nullable-types + - Curl: . The CURLOPT_BINARYTRANSFER constant is deprecated. diff --git a/Zend/tests/bug63635.phpt b/Zend/tests/bug63635.phpt index 09f893615878d..e2f85e49e6ed1 100644 --- a/Zend/tests/bug63635.phpt +++ b/Zend/tests/bug63635.phpt @@ -6,7 +6,7 @@ class Node { public $parent = NULL; public $children = array(); - function __construct(Node $parent=NULL) { + function __construct(?Node $parent=NULL) { if ($parent) { $parent->children[] = $this; } diff --git a/Zend/tests/bug71428.1.phpt b/Zend/tests/bug71428.1.phpt index be7c7f4826fb4..686afef78d22f 100644 --- a/Zend/tests/bug71428.1.phpt +++ b/Zend/tests/bug71428.1.phpt @@ -3,7 +3,7 @@ bug #71428.1: inheritance with null default values --FILE-- --EXPECTF-- +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + Fatal error: Declaration of C::m(A $a, $n) must be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4 diff --git a/Zend/tests/bug72119.phpt b/Zend/tests/bug72119.phpt index b374bcc007720..b6ea9cf27e568 100644 --- a/Zend/tests/bug72119.phpt +++ b/Zend/tests/bug72119.phpt @@ -3,7 +3,7 @@ Bug #72119 (Interface declaration compatibility regression with default values) --FILE-- --EXPECTF-- +Deprecated: Implicitly marking parameter $x as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d NULL object(stdClass)#%d (0) { } diff --git a/Zend/tests/ns_074.phpt b/Zend/tests/ns_074.phpt index 37d4e7dc3a94e..88a64f70e3e9b 100644 --- a/Zend/tests/ns_074.phpt +++ b/Zend/tests/ns_074.phpt @@ -5,7 +5,7 @@ Testing type-hinted lambda parameter inside namespace namespace foo; -$x = function (\stdclass $x = NULL) { +$x = function (?\stdclass $x = NULL) { var_dump($x); }; diff --git a/Zend/tests/required_param_after_optional.phpt b/Zend/tests/required_param_after_optional.phpt index c3a925efe88ac..6b9d7610805e1 100644 --- a/Zend/tests/required_param_after_optional.phpt +++ b/Zend/tests/required_param_after_optional.phpt @@ -13,6 +13,10 @@ Deprecated: Optional parameter $testA declared before required parameter $testC Deprecated: Optional parameter $testB declared before required parameter $testC is implicitly treated as a required parameter in %s on line %d +Deprecated: Implicitly marking parameter $test2A as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + Deprecated: Optional parameter $test2B declared before required parameter $test2C is implicitly treated as a required parameter in %s on line %d +Deprecated: Implicitly marking parameter $test3A as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + Deprecated: Optional parameter $test3B declared before required parameter $test3C is implicitly treated as a required parameter in %s on line %d diff --git a/Zend/tests/traits/bug60717.phpt b/Zend/tests/traits/bug60717.phpt index dc9175ac67ce8..d713f36acdb3e 100644 --- a/Zend/tests/traits/bug60717.phpt +++ b/Zend/tests/traits/bug60717.phpt @@ -69,5 +69,10 @@ namespace HTML echo 'Done'; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $attributes as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + +Deprecated: Implicitly marking parameter $attributes as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + +Deprecated: Implicitly marking parameter $attributes as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d Done diff --git a/Zend/tests/type_declarations/callable_003.phpt b/Zend/tests/type_declarations/callable_003.phpt index 6e6095cd737ea..c266fe13c35ff 100644 --- a/Zend/tests/type_declarations/callable_003.phpt +++ b/Zend/tests/type_declarations/callable_003.phpt @@ -13,7 +13,8 @@ function bar(callable $a = null) { foo("strpos", 123, "strpos"); bar("substr"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d string(6) "strpos" int(123) string(6) "strpos" diff --git a/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type.phpt b/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type.phpt index d3dab0d75e0df..4efea911e3d9f 100644 --- a/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type.phpt +++ b/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type.phpt @@ -10,5 +10,6 @@ function foo(X&Y $foo = null) { foo(null); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $foo as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d NULL diff --git a/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type_error.phpt b/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type_error.phpt index 65fc16e6d2c47..bd2bc272e90f0 100644 --- a/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type_error.phpt +++ b/Zend/tests/type_declarations/intersection_types/implicit_nullable_intersection_type_error.phpt @@ -15,4 +15,5 @@ try { ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $foo as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d foo(): Argument #1 ($foo) must be of type (X&Y)|null, int given, called in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_002.phpt b/Zend/tests/type_declarations/iterable/iterable_002.phpt index d1e1b09d187ac..3affb4ade7339 100644 --- a/Zend/tests/type_declarations/iterable/iterable_002.phpt +++ b/Zend/tests/type_declarations/iterable/iterable_002.phpt @@ -17,4 +17,6 @@ function baz(iterable $iterable = 1) { ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $iterable as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + Fatal error: Cannot use int as default value for parameter $iterable of type Traversable|array in %s on line %d diff --git a/Zend/tests/type_declarations/literal_types/false_standalone_implicit_nullability.phpt b/Zend/tests/type_declarations/literal_types/false_standalone_implicit_nullability.phpt index c5fe5f76cf79d..66884dcbe6d1e 100644 --- a/Zend/tests/type_declarations/literal_types/false_standalone_implicit_nullability.phpt +++ b/Zend/tests/type_declarations/literal_types/false_standalone_implicit_nullability.phpt @@ -8,6 +8,7 @@ function test(false $v = null) { return $v; } var_dump(test(false)); var_dump(test(null)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $v as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d bool(false) NULL diff --git a/Zend/tests/type_declarations/literal_types/true_standalone_implicit_nullability.phpt b/Zend/tests/type_declarations/literal_types/true_standalone_implicit_nullability.phpt index d460742689e23..8905fb9e5b94b 100644 --- a/Zend/tests/type_declarations/literal_types/true_standalone_implicit_nullability.phpt +++ b/Zend/tests/type_declarations/literal_types/true_standalone_implicit_nullability.phpt @@ -8,6 +8,7 @@ function test(true $v = null) { return $v; } var_dump(test(true)); var_dump(test(null)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $v as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d bool(true) NULL diff --git a/Zend/tests/type_declarations/nullable_null.phpt b/Zend/tests/type_declarations/nullable_null.phpt index 8991db5e8858f..04e3e50c42aad 100644 --- a/Zend/tests/type_declarations/nullable_null.phpt +++ b/Zend/tests/type_declarations/nullable_null.phpt @@ -7,5 +7,6 @@ function test(Foo $a = null) { } test(null); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d ok diff --git a/Zend/tests/type_declarations/scalar_none.phpt b/Zend/tests/type_declarations/scalar_none.phpt index 5b639757c0eb2..822311e07472f 100644 --- a/Zend/tests/type_declarations/scalar_none.phpt +++ b/Zend/tests/type_declarations/scalar_none.phpt @@ -8,10 +8,10 @@ $functions = [ 'float' => function (float $f) { return $f; }, 'string' => function (string $s) { return $s; }, 'bool' => function (bool $b) { return $b; }, - 'int nullable' => function (int $i = NULL) { return $i; }, - 'float nullable' => function (float $f = NULL) { return $f; }, - 'string nullable' => function (string $s = NULL) { return $s; }, - 'bool nullable' => function (bool $b = NULL) { return $b; } + 'int nullable' => function (?int $i = NULL) { return $i; }, + 'float nullable' => function (?float $f = NULL) { return $f; }, + 'string nullable' => function (?string $s = NULL) { return $s; }, + 'bool nullable' => function (?bool $b = NULL) { return $b; } ]; foreach ($functions as $type => $function) { diff --git a/Zend/tests/type_declarations/scalar_null.phpt b/Zend/tests/type_declarations/scalar_null.phpt index d1ade3ad48c43..f036f8600f93b 100644 --- a/Zend/tests/type_declarations/scalar_null.phpt +++ b/Zend/tests/type_declarations/scalar_null.phpt @@ -8,10 +8,10 @@ $functions = [ 'float' => function (float $f) { return $f; }, 'string' => function (string $s) { return $s; }, 'bool' => function (bool $b) { return $b; }, - 'int nullable' => function (int $i = NULL) { return $i; }, - 'float nullable' => function (float $f = NULL) { return $f; }, - 'string nullable' => function (string $s = NULL) { return $s; }, - 'bool nullable' => function (bool $b = NULL) { return $b; } + 'int nullable' => function (?int $i) { return $i; }, + 'float nullable' => function (?float $f) { return $f; }, + 'string nullable' => function (?string $s) { return $s; }, + 'bool nullable' => function (?bool $b) { return $b; } ]; foreach ($functions as $type => $function) { diff --git a/Zend/tests/type_declarations/variance/internal_parent/unresolvable_inheritance_check_param.phpt b/Zend/tests/type_declarations/variance/internal_parent/unresolvable_inheritance_check_param.phpt index d1a1ad78ce30a..a311aa3aea0fc 100644 --- a/Zend/tests/type_declarations/variance/internal_parent/unresolvable_inheritance_check_param.phpt +++ b/Zend/tests/type_declarations/variance/internal_parent/unresolvable_inheritance_check_param.phpt @@ -4,7 +4,7 @@ Test unresolvable inheritance check due to unavailable parameter type when the p diff --git a/Zend/tests/variadic/adding_additional_optional_parameter.phpt b/Zend/tests/variadic/adding_additional_optional_parameter.phpt index b4e797803dcf2..3b6b8cea4f53a 100644 --- a/Zend/tests/variadic/adding_additional_optional_parameter.phpt +++ b/Zend/tests/variadic/adding_additional_optional_parameter.phpt @@ -8,10 +8,10 @@ interface DB { } class MySQL implements DB { - public function query($query, string $extraParam = null, string ...$params) { } + public function query($query, ?string $extraParam = null, string ...$params) { } } ?> ===DONE=== ---EXPECT-- +--EXPECTF-- ===DONE=== diff --git a/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt b/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt index a04cd84f5ea44..ef7da929367d8 100644 --- a/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt +++ b/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt @@ -8,7 +8,7 @@ interface DB { } class MySQL implements DB { - public function query($query, int $extraParam = null, string ...$params) { } + public function query($query, ?int $extraParam = null, string ...$params) { } } ?> diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3ca643b101ca0..4077ef4ef080a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7224,6 +7224,11 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; arg_info->type = zend_compile_typename_ex(type_ast, force_nullable, &forced_allow_nullable); + if (forced_allow_nullable) { + zend_error(E_DEPRECATED, + "Implicitly marking parameter $%s as nullable is deprecated, the explicit nullable type " + "must be used instead", ZSTR_VAL(name)); + } if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); diff --git a/ext/date/tests/DateTime_extends_basic2.phpt b/ext/date/tests/DateTime_extends_basic2.phpt index 03d1e0328339f..970e95ec9d58b 100644 --- a/ext/date/tests/DateTime_extends_basic2.phpt +++ b/ext/date/tests/DateTime_extends_basic2.phpt @@ -10,7 +10,7 @@ echo "*** Testing new DateTime() : with user space __construct magic method ***\ class DateTimeExt extends DateTime { - public function __construct ($date = null, DateTimeZone $dtz = null) + public function __construct ($date = null, ?DateTimeZone $dtz = null) { if($dtz === null) { diff --git a/ext/date/tests/bug55407.phpt b/ext/date/tests/bug55407.phpt index f478a52129826..d87e588ae3acd 100644 --- a/ext/date/tests/bug55407.phpt +++ b/ext/date/tests/bug55407.phpt @@ -6,7 +6,7 @@ error_reporting=-1 diff --git a/ext/opcache/tests/opt/assign_op_002.phpt b/ext/opcache/tests/opt/assign_op_002.phpt index 63746ac1c86b6..7085ea63ff47c 100644 --- a/ext/opcache/tests/opt/assign_op_002.phpt +++ b/ext/opcache/tests/opt/assign_op_002.phpt @@ -6,7 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 --FILE-- run($this); } diff --git a/ext/reflection/tests/ReflectionClass_export_basic1.phpt b/ext/reflection/tests/ReflectionClass_export_basic1.phpt index bbe0bed6dc4b1..0931e5e123064 100644 --- a/ext/reflection/tests/ReflectionClass_export_basic1.phpt +++ b/ext/reflection/tests/ReflectionClass_export_basic1.phpt @@ -6,7 +6,7 @@ Class A { public function privf(Exception $a) {} public function pubf(A $a, $b, - C $c = null, + ?C $c = null, $d = K, $e = "15 chars long -", $f = null, @@ -20,6 +20,7 @@ define('K', "16 chars long --"); echo new ReflectionClass("C"), "\n"; ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $h as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d Class [ class C extends A ] { @@ %s 14-14 diff --git a/ext/reflection/tests/bug62715.phpt b/ext/reflection/tests/bug62715.phpt index b0080b6da63b4..e8eecf5c41179 100644 --- a/ext/reflection/tests/bug62715.phpt +++ b/ext/reflection/tests/bug62715.phpt @@ -3,7 +3,7 @@ Bug #62715 (ReflectionParameter::isDefaultValueAvailable() wrong result) --FILE-- getParameters() as $p) { @@ -17,6 +17,8 @@ foreach ($r->getParameters() as $p) { } ?> --EXPECTF-- +Deprecated: Optional parameter $a declared before required parameter $c is implicitly treated as a required parameter in %s on line %d + Deprecated: Optional parameter $b declared before required parameter $c is implicitly treated as a required parameter in %s on line %d bool(false) bool(false) diff --git a/ext/reflection/tests/parameters_002.phpt b/ext/reflection/tests/parameters_002.phpt index e51f67df6f180..0ace42b100a4a 100644 --- a/ext/reflection/tests/parameters_002.phpt +++ b/ext/reflection/tests/parameters_002.phpt @@ -11,7 +11,7 @@ function test($nix, Array $ar, &$ref, stdClass $std, class test { function method($nix, Array $ar, &$ref, stdClass $std, - NonExistingClass $na, stdClass $opt = NULL, $def = "FooBar") + NonExistingClass $na, ?stdClass $opt = NULL, $def = "FooBar") { } } @@ -73,6 +73,7 @@ check_params(ReflectionMethod::createFromMethodName('test::method')); ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $opt as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d #####test()##### ===0=== getName: string(3) "nix" diff --git a/ext/reflection/tests/types/ReflectionType_001.phpt b/ext/reflection/tests/types/ReflectionType_001.phpt index b4baf5355c038..4791be9aef6ca 100644 --- a/ext/reflection/tests/types/ReflectionType_001.phpt +++ b/ext/reflection/tests/types/ReflectionType_001.phpt @@ -100,7 +100,8 @@ $obj->std = new stdClass; $r = (new ReflectionProperty($obj, 'std'))->getType(); var_dump($r->getName()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $d as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d *** functions ** Function 0 - Parameter 0 bool(true) diff --git a/ext/reflection/tests/types/pure_intersection_type_implicitly_nullable.phpt b/ext/reflection/tests/types/pure_intersection_type_implicitly_nullable.phpt index de2474cfbd495..3cad1b3ba255c 100644 --- a/ext/reflection/tests/types/pure_intersection_type_implicitly_nullable.phpt +++ b/ext/reflection/tests/types/pure_intersection_type_implicitly_nullable.phpt @@ -24,7 +24,8 @@ function foo(X&Y $foo = null) { dumpType((new ReflectionFunction('foo'))->getParameters()[0]->getType()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $foo as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d Type (X&Y)|null is ReflectionUnionType: Allows Null: true Type X&Y is ReflectionIntersectionType: diff --git a/ext/spl/tests/bug65328.phpt b/ext/spl/tests/bug65328.phpt index 518418654f4b8..7438a4b876ade 100644 --- a/ext/spl/tests/bug65328.phpt +++ b/ext/spl/tests/bug65328.phpt @@ -13,7 +13,7 @@ class Tree */ protected $head; - public function __construct(Node $head = null) + public function __construct(?Node $head = null) { $this->head = $head ? : new Node('HEAD'); } @@ -109,10 +109,10 @@ class Node extends \RecursiveArrayIterator implements \Countable /** * @param mixed $data * @param mixed $uid - * @param Node $parent + * @param Node|null $parent * @param bool $assureUnique */ - public function __construct($data, $uid = null, Node $parent = null, $assureUnique = false) + public function __construct($data, $uid = null, ?Node $parent = null, $assureUnique = false) { if(null !== $parent) { $this->parent = $parent; diff --git a/sapi/fpm/tests/logreader.inc b/sapi/fpm/tests/logreader.inc index 51a7104d01f3f..8d742d0bba64f 100644 --- a/sapi/fpm/tests/logreader.inc +++ b/sapi/fpm/tests/logreader.inc @@ -166,10 +166,10 @@ class LogReader */ public function readUntil( callable $matcher, - string $notFoundMessage = null, + ?string $notFoundMessage = null, bool $checkAllLogs = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { if (is_null($timeoutSeconds) && is_null($timeoutMicroseconds)) { $timeoutSeconds = 3; diff --git a/sapi/fpm/tests/logtool.inc b/sapi/fpm/tests/logtool.inc index fc2043b84efe1..5a02d4a899ec3 100644 --- a/sapi/fpm/tests/logtool.inc +++ b/sapi/fpm/tests/logtool.inc @@ -138,10 +138,10 @@ class LogTool */ private function match( callable $matcher, - string $notFoundMessage = null, + ?string $notFoundMessage = null, bool $checkAllLogs = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { if ($this->getError()) { return false; @@ -169,7 +169,7 @@ class LogTool * @return bool * @throws \Exception */ - public function checkTruncatedMessage(string $line = null): bool + public function checkTruncatedMessage(?string $line = null): bool { if ($this->message === null) { throw new \LogicException('The message has not been set'); @@ -355,7 +355,7 @@ class LogTool * * @return bool */ - private function checkLineLength(string $line, int $lineLen = null): bool + private function checkLineLength(string $line, ?int $lineLen = null): bool { $lineLen = $lineLen ?: strlen($line); if ($lineLen > $this->limit) { @@ -569,7 +569,7 @@ class LogTool public function readAllEntries( string $type, string $expectedMessage, - string $pool = null, + ?string $pool = null, string $ignoreErrorFor = self::DEBUG ): bool { if ($this->getError()) { @@ -604,12 +604,12 @@ class LogTool public function expectEntry( string $type, string $expectedMessage, - string $pool = null, + ?string $pool = null, string $ignoreErrorFor = self::DEBUG, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { if ($this->getError()) { return false; @@ -639,7 +639,7 @@ class LogTool * @return bool * @throws \Exception */ - public function expectDebug(string $expectedMessage, string $pool = null): bool + public function expectDebug(string $expectedMessage, ?string $pool = null): bool { return $this->expectEntry(self::DEBUG, $expectedMessage, $pool, self::ERROR); } @@ -653,7 +653,7 @@ class LogTool * @return bool * @throws \Exception */ - public function expectNotice(string $expectedMessage, string $pool = null): bool + public function expectNotice(string $expectedMessage, ?string $pool = null): bool { return $this->expectEntry(self::NOTICE, $expectedMessage, $pool); } @@ -667,7 +667,7 @@ class LogTool * @return bool * @throws \Exception */ - public function expectWarning(string $expectedMessage, string $pool = null): bool + public function expectWarning(string $expectedMessage, ?string $pool = null): bool { return $this->expectEntry(self::WARNING, $expectedMessage, $pool); } @@ -681,7 +681,7 @@ class LogTool * @return bool * @throws \Exception */ - public function expectError(string $expectedMessage, string $pool = null): bool + public function expectError(string $expectedMessage, ?string $pool = null): bool { return $this->expectEntry(self::ERROR, $expectedMessage, $pool); } @@ -695,7 +695,7 @@ class LogTool * @return bool * @throws \Exception */ - public function expectAlert(string $expectedMessage, string $pool = null): bool + public function expectAlert(string $expectedMessage, ?string $pool = null): bool { return $this->expectEntry(self::ALERT, $expectedMessage, $pool); } @@ -716,8 +716,8 @@ class LogTool string $pattern, bool $invert = false, bool $checkAllLogs = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null, + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null, ): bool { $matchResult = $this->match( function ($line) use ($pattern) { @@ -755,10 +755,10 @@ class LogTool */ private function getMatchDebugMessage( string $title, - string $pattern = null, - string $line = null, - string $expectedMessage = null, - string $actualMessage = null + ?string $pattern = null, + ?string $line = null, + ?string $expectedMessage = null, + ?string $actualMessage = null ): string { $msg = "$title:\n"; if ($pattern !== null) { @@ -788,10 +788,10 @@ class LogTool */ private function traceMatch( string $title, - string $pattern = null, - string $line = null, - string $expectedMessage = null, - string $actualMessage = null + ?string $pattern = null, + ?string $line = null, + ?string $expectedMessage = null, + ?string $actualMessage = null ): void { if ($this->debug) { echo "LogTool - " . $this->getMatchDebugMessage($title, $pattern, $line, $expectedMessage, $actualMessage); @@ -820,7 +820,7 @@ class LogTool * * @return false */ - private function error(string $msg, string $line = null, string $ignoreFor = self::DEBUG): bool + private function error(string $msg, ?string $line = null, string $ignoreFor = self::DEBUG): bool { if ($this->error === null && ($line === null || ! str_contains($line, $ignoreFor))) { $this->trace("Setting error: $msg"); diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 84759c4a2c85a..259c038181f75 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -355,7 +355,7 @@ class Tester * @param string $command * @param string|null $expectedPartOfOutput */ - static public function skipIfShellCommandFails(string $command, string $expectedPartOfOutput = null) + static public function skipIfShellCommandFails(string $command, ?string $expectedPartOfOutput = null) { $result = exec("$command 2>&1", $output, $code); if ($result === false || $code) { @@ -397,8 +397,8 @@ class Tester string|array $configTemplate, string $code = '', array $options = [], - string $fileName = null, - bool $debug = null, + ?string $fileName = null, + ?bool $debug = null, string $clientTransport = 'stream' ) { $this->configTemplate = $configTemplate; @@ -599,7 +599,7 @@ class Tester */ public function checkConnection( string $host = '127.0.0.1', - string $successMessage = null, + ?string $successMessage = null, ?string $errorMessage = 'Connection failed', int $attempts = 20, int $delay = 50000 @@ -636,8 +636,8 @@ class Tester */ public function checkRequest( string $address, - string $successMessage = null, - string $errorMessage = null, + ?string $successMessage = null, + ?string $errorMessage = null, string $uri = '/ping', string $query = '', array $headers = [] @@ -673,7 +673,7 @@ class Tester */ public function status( array $expectedFields, - string $address = null, + ?string $address = null, string $statusPath = '/status', $formats = ['plain', 'html', 'xml', 'json', 'openmetrics'] ) { @@ -704,9 +704,9 @@ class Tester private function getRequestParams( string $query = '', array $headers = [], - string $uri = null, - string $scriptFilename = null, - string $scriptName = null, + ?string $uri = null, + ?string $scriptFilename = null, + ?string $scriptName = null, ?string $stdin = null, ?string $method = null, ): array { @@ -835,15 +835,15 @@ class Tester public function request( string $query = '', array $headers = [], - string $uri = null, - string $address = null, - string $successMessage = null, - string $errorMessage = null, + ?string $uri = null, + ?string $address = null, + ?string $successMessage = null, + ?string $errorMessage = null, bool $connKeepAlive = false, bool $socketKeepAlive = false, - string $scriptFilename = null, - string $scriptName = null, - string|array $stdin = null, + ?string $scriptFilename = null, + ?string $scriptName = null, + string|array|null $stdin = null, bool $expectError = false, int $readLimit = -1, int $writeDelay = 0, @@ -904,9 +904,9 @@ class Tester */ public function multiRequest( int|array $requests, - string $address = null, - string $successMessage = null, - string $errorMessage = null, + ?string $address = null, + ?string $successMessage = null, + ?string $errorMessage = null, bool $connKeepAlive = false, bool $socketKeepAlive = false, int $readTimeout = 0, @@ -977,7 +977,7 @@ class Tester * @throws \Exception */ public function requestValues( - string $address = null, + ?string $address = null, bool $connKeepAlive = false, bool $socketKeepAlive = false ): ValuesResponse { @@ -1010,7 +1010,7 @@ class Tester * @return Client */ private function getClient( - string $address = null, + ?string $address = null, bool $connKeepAlive = false, bool $socketKeepAlive = false ): Client { @@ -1119,7 +1119,7 @@ class Tester * * @return string */ - public function signal($signal, int $pid = null) + public function signal($signal, ?int $pid = null) { if (is_null($pid)) { $pid = $this->getPid(); @@ -1405,7 +1405,7 @@ class Tester * * @return string */ - private function getFile(string $extension, string $dir = null, string $name = null): string + private function getFile(string $extension, ?string $dir = null, ?string $name = null): string { $fileName = (is_null($name) ? $this->fileName : $name . '.') . $extension; @@ -1446,7 +1446,7 @@ class Tester * * @return string */ - public function getPrefixedFile(string $extension, string $prefix = null): string + public function getPrefixedFile(string $extension, ?string $prefix = null): string { $fileName = rtrim($this->fileName, '.'); if ( ! is_null($prefix)) { @@ -1469,8 +1469,8 @@ class Tester private function makeFile( string $extension, string $content = '', - string $dir = null, - string $name = null, + ?string $dir = null, + ?string $name = null, bool $overwrite = true ): string { $filePath = $this->getFile($extension, $dir, $name); @@ -1559,7 +1559,7 @@ class Tester * * @return false */ - private function error(string $msg, \Exception $exception = null, bool $prefix = true): bool + private function error(string $msg, ?\Exception $exception = null, bool $prefix = true): bool { $this->error = $prefix ? 'ERROR: ' . $msg : ltrim($msg); if ($exception) { @@ -1719,8 +1719,8 @@ class Tester public function expectLogPattern( string $pattern, bool $checkAllLogs = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null, + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null, ) { $this->logTool->expectPattern( $pattern, @@ -1744,8 +1744,8 @@ class Tester public function expectNoLogPattern( string $pattern, bool $checkAllLogs = true, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null, + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null, ) { if (is_null($timeoutSeconds) && is_null($timeoutMicroseconds)) { $timeoutMicroseconds = 10; @@ -1826,12 +1826,12 @@ class Tester private function expectLogEntry( string $type, string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null, + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null, string $ignoreErrorFor = LogTool::DEBUG ): bool { for ($i = 0; $i < $count; $i++) { @@ -1870,12 +1870,12 @@ class Tester */ public function expectLogDebug( string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { return $this->expectLogEntry( LogTool::DEBUG, @@ -1906,12 +1906,12 @@ class Tester */ public function expectLogNotice( string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { return $this->expectLogEntry( LogTool::NOTICE, @@ -1941,12 +1941,12 @@ class Tester */ public function expectLogWarning( string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { return $this->expectLogEntry( LogTool::WARNING, @@ -1976,12 +1976,12 @@ class Tester */ public function expectLogError( string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { return $this->expectLogEntry( LogTool::ERROR, @@ -2011,12 +2011,12 @@ class Tester */ public function expectLogAlert( string $message, - string $pool = null, + ?string $pool = null, int $count = 1, bool $checkAllLogs = false, bool $invert = false, - int $timeoutSeconds = null, - int $timeoutMicroseconds = null + ?int $timeoutSeconds = null, + ?int $timeoutMicroseconds = null ): bool { return $this->expectLogEntry( LogTool::ALERT, @@ -2164,7 +2164,7 @@ class Tester * @return bool * @throws \Exception */ - public function readAllLogEntries(string $type, string $message, string $pool = null): bool + public function readAllLogEntries(string $type, string $message, ?string $pool = null): bool { return $this->logTool->readAllEntries($type, $message, $pool); } @@ -2178,7 +2178,7 @@ class Tester * @return bool * @throws \Exception */ - public function readAllLogNotices(string $message, string $pool = null): bool + public function readAllLogNotices(string $message, ?string $pool = null): bool { return $this->readAllLogEntries(LogTool::NOTICE, $message, $pool); } @@ -2205,7 +2205,7 @@ class Tester */ private function trace( string $title, - string|array $message = null, + string|array|null $message = null, bool $isCommand = false, bool $isFile = false ): void { diff --git a/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt index aa97fb75fbd76..78c76d4eece04 100644 --- a/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt +++ b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt @@ -30,7 +30,7 @@ final class StreamWrapper string $path, string $mode, int $options = 0, - string &$openedPath = null + ?string &$openedPath = null ) : bool { if ($mode[0] !== 'r') { return false; diff --git a/tests/classes/type_hinting_003.phpt b/tests/classes/type_hinting_003.phpt index fab088daae8fa..72a31190cfe71 100644 --- a/tests/classes/type_hinting_003.phpt +++ b/tests/classes/type_hinting_003.phpt @@ -39,6 +39,7 @@ Test::f1(1); ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $ar as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d Test::f1() array(1) { [0]=> diff --git a/tests/classes/type_hinting_004.phpt b/tests/classes/type_hinting_004.phpt index 2ba8870b0a047..7983f09333b55 100644 --- a/tests/classes/type_hinting_004.phpt +++ b/tests/classes/type_hinting_004.phpt @@ -143,6 +143,11 @@ Ensure type hints are enforced for functions invoked as callbacks. ?> --EXPECTF-- +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d + +Deprecated: Implicitly marking parameter $a as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d ---> Type hints with callback function: 0: f1(): Argument #1 ($a) must be of type A, int given%s(%d) diff --git a/tests/lang/type_hints_002.phpt b/tests/lang/type_hints_002.phpt index 36fe56ad4b3ad..8110c0d095cc4 100644 --- a/tests/lang/type_hints_002.phpt +++ b/tests/lang/type_hints_002.phpt @@ -15,7 +15,8 @@ $o->f(new P); $o->f(); $o->f(NULL); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Implicitly marking parameter $p as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d object(P)#2 (0) { } -