Skip to content

[RFC] Deprecate implicit nullable parameter types #12959

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

Merged
merged 1 commit into from
Mar 13, 2024
Merged
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
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/bug63635.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/bug71428.1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ bug #71428.1: inheritance with null default values
--FILE--
<?php
class A {
public function m(array $a = null) {}
public function m(?array $a = null) {}
}
class B extends A {
public function m(array $a = []) {}
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug71428.3.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ class B { public function m(A $a = NULL, $n) { echo "B.m";} };
class C extends B { public function m(A $a , $n) { echo "C.m";} };
?>
--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
2 changes: 1 addition & 1 deletion Zend/tests/bug72119.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Bug #72119 (Interface declaration compatibility regression with default values)
--FILE--
<?php
interface Foo {
public function bar(array $baz = null);
public function bar(?array $baz = null);
}

class Hello implements Foo {
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/gh11488.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ function c(
--EXPECTF--
Deprecated: Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter in %s on line %d

Deprecated: Implicitly marking parameter $c as nullable is deprecated, the explicit nullable type must be used instead in %s on line %d

Deprecated: Optional parameter $e declared before required parameter $f is implicitly treated as a required parameter in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/ns_070.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Testing parameter type-hinted with default value inside namespace
namespace foo;

class bar {
public function __construct(\stdclass $x = NULL) {
public function __construct(?\stdclass $x = NULL) {
var_dump($x);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/ns_071.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Testing parameter type-hinted (array) with default value inside namespace
namespace foo;

class bar {
public function __construct(array $x = NULL) {
public function __construct(?array $x = NULL) {
var_dump($x);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Zend/tests/ns_072.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface foo {
}

class bar {
public function __construct(foo $x = NULL) {
public function __construct(?foo $x = NULL) {
var_dump($x);
}
}
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/ns_073.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $x(new \stdclass);

?>
--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) {
}
2 changes: 1 addition & 1 deletion Zend/tests/ns_074.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down
4 changes: 4 additions & 0 deletions Zend/tests/required_param_after_optional.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion Zend/tests/traits/bug60717.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 2 additions & 1 deletion Zend/tests/type_declarations/callable_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions Zend/tests/type_declarations/iterable/iterable_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 2 additions & 1 deletion Zend/tests/type_declarations/nullable_null.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions Zend/tests/type_declarations/scalar_none.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/type_declarations/scalar_null.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Test unresolvable inheritance check due to unavailable parameter type when the p
<?php

class Test extends DateTime {
public static function createFromFormat($format, $datetime, Wrong $timezone = null): DateTime|false {}
public static function createFromFormat($format, $datetime, ?Wrong $timezone = null): DateTime|false {}
}

?>
Expand Down
4 changes: 2 additions & 2 deletions Zend/tests/variadic/adding_additional_optional_parameter.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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===
Original file line number Diff line number Diff line change
Expand Up @@ -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) { }
}

?>
Expand Down
5 changes: 5 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion ext/date/tests/DateTime_extends_basic2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion ext/date/tests/bug55407.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ error_reporting=-1
<?php namespace melt\core;

class DateTime extends \DateTime {
public static function createFromFormat($format, $time, \DateTimeZone $timezone = null): DateTime|false {
public static function createFromFormat($format, $time, ?\DateTimeZone $timezone = null): DateTime|false {
return new DateTime(parent::createFromFormat($format, $time, $timezone));
}
}
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug73746.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CountryMapping
const CZ = 'CZ';
const EN = 'EN';

public function get(string $countryIsoCode = null) : string // Works correctly if return type is removed
public function get(?string $countryIsoCode = null) : string // Works correctly if return type is removed
{
switch (strtoupper($countryIsoCode)) {
case 'CZ':
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/tests/bug74442.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ opcache
--FILE--
<?php
class Schema_Base {
public function addField($typeclass, array $params = null) {
public function addField($typeclass, ?array $params = null) {
$field = new $typeclass($params);
return $field;
}
}

class Field_Base {
public function __construct(array $params = null) {
public function __construct(?array $params = null) {
if (! is_array($params)) {
$params = (array) $params;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/invalid_array_key_type.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ opcache
--FILE--
<?php

function test(\SplObjectStorage $definitions = null) {
function test(?\SplObjectStorage $definitions = null) {
$argument = new stdClass;
$definitions[$argument] = 1;
$definitions[$argument] += 1;
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/jit/cast_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ opcache.jit=1205
opcache
--FILE--
<?php
function foo (int $x = null) {
function foo (?int $x = null) {
$a = (array)$x;
$a[] = 42;
var_dump($a);
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/jit/send_var_ex_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ for ($i = 0; $i < 3; $i++ ) {
var_dump($x);
}

function test(&$a = null, SomeType &$b = null) {
function test(&$a = null, ?SomeType &$b = null) {
$a++;
}
?>
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/opt/assign_op_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ opcache.enable_cli=1
opcache.optimization_level=-1
--FILE--
<?php
function foo(int $a = null) {
function foo(?int $a = null) {
$a -= 1;
return $a;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/pdo_pgsql/tests/bug72294.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class PHPUnit_Framework_TestCase
private $name = null;
private $result;

public function run(PHPUnit_Framework_TestResult $result = null)
public function run(?PHPUnit_Framework_TestResult $result = null)
{
$result->run($this);
}
Expand Down
3 changes: 2 additions & 1 deletion ext/reflection/tests/ReflectionClass_export_basic1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 [ <user> class C extends A ] {
@@ %s 14-14

Expand Down
4 changes: 3 additions & 1 deletion ext/reflection/tests/bug62715.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Bug #62715 (ReflectionParameter::isDefaultValueAvailable() wrong result)
--FILE--
<?php

function test(PDO $a = null, $b = 0, array $c) {}
function test(?PDO $a = null, $b = 0, array $c) {}
$r = new ReflectionFunction('test');

foreach ($r->getParameters() as $p) {
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion ext/reflection/tests/parameters_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
{
}
}
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion ext/reflection/tests/types/ReflectionType_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading