Take the State of PHP 2026 Survey →

Deprecate passing null to non-nullable arguments of internal functions View as Markdown

Implemented (PHP 8.1)
Authors
Nikita Popov nikic@php.net
Date
2020-12-01
Target
PHP 8.1
Implementation
https://github.com/php/php-src/pull/6475
Source
wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg

Vote

Deprecate passing null to non-nullable arguments of internal functions? closed
Yes
46
No
0
46 voters
alcaeus Yes 2021-02-08 11:27
as Yes 2021-01-28 17:53
asgrim Yes 2021-01-26 10:15
ashnazg Yes 2021-01-28 13:22
beberlei Yes 2021-02-04 16:54
bishop Yes 2021-01-27 01:18
brzuchal Yes 2021-01-26 11:01
cmb Yes 2021-02-03 14:47
crell Yes 2021-01-26 14:22
derick Yes 2021-01-26 10:09
dharman Yes 2021-01-26 15:26
duodraco Yes 2021-02-03 18:58
galvao Yes 2021-01-26 10:32
girgias Yes 2021-01-26 14:49
heiglandreas Yes 2021-02-06 08:54
ilutov Yes 2021-01-26 10:23
jasny Yes 2021-01-30 16:33
jhdxr Yes 2021-01-27 13:21
kalle Yes 2021-01-26 13:51
kguest Yes 2021-02-03 21:50
klaussilveira Yes 2021-02-03 16:35
kocsismate Yes 2021-01-26 10:38
krakjoe Yes 2021-02-05 08:24
kriscraig Yes 2021-01-26 10:28
lcobucci Yes 2021-02-04 14:32
marandall Yes 2021-01-26 12:41
mariano Yes 2021-02-06 00:38
mauricio Yes 2021-02-04 18:41
mbeccati Yes 2021-01-27 15:33
mcmic Yes 2021-01-26 10:08
narf Yes 2021-01-26 10:58
nicolasgrekas Yes 2021-01-26 10:13
nikic Yes 2021-01-26 09:58
ocramius Yes 2021-01-26 10:25
petk Yes 2021-01-30 10:14
ramsey Yes 2021-01-26 14:52
reywob Yes 2021-01-26 12:02
sebastian Yes 2021-01-28 09:29
sergey Yes 2021-02-02 08:05
sirsnyder Yes 2021-01-26 21:16
svpernova09 Yes 2021-01-26 14:18
tandre Yes 2021-02-06 14:08
theodorejb Yes 2021-01-26 15:04
trowski Yes 2021-01-26 16:06
villfa Yes 2021-01-27 13:11
wyrihaximus Yes 2021-02-03 20:18

Discussions on the mailing list

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:50 UTC

Introduction

Internal functions (defined by PHP or PHP extensions) currently silently accept null values for non-nullable arguments in coercive typing mode. This is contrary to the behavior of user-defined functions, which only accept null for nullable arguments. This RFC aims to resolve this inconsistency.

For example, this code currently runs without producing any diagnostics:

var_dump(str_contains("foobar", null));
// bool(true)

The null value is silently converted into an empty string and str_contains() thus returns true.

However, the behavior is different for user-defined functions. For example, consider the same function being defined as a polyfill:

// Inside a polyfill:
function str_contains(string $haystack, string $needle): bool {
    return false !== strpos($haystack, $needle);
}
 
var_dump(str_contains("foobar", null));
// TypeError: str_contains(): Argument #2 ($needle) must be of type string, null given

After the changes in PHP 8.0, this is the only remaining fundamental difference in behavior between user-defined and internal functions. This makes it infeasible to accurately polyfill functions, and will complicate long-term projects such as migrating the standard library to be partially implemented in PHP rather than C.

Historically, the reason for this discrepancy is that internal functions have supported a concept of scalar types (bool, int, float, string) long before they were introduced for user-defined functions in PHP 7.0, and the existing implementation silently accepted null values. For the new scalar type declarations introduced in PHP 7.0 an explicit choice was made to not accept null values to non-nullable arguments, but changing the existing behavior of internal functions would have been too disruptive at the time.

This RFC proposes to synchronize the behavior of internal functions, by throwing a deprecation warning in PHP 8.1, which will become a TypeError in the next major version.

var_dump(str_contains("foobar", null));
// Deprecated: Passing null to argument of type string is deprecated

Proposal

If

  • null is passed to an argument of an internal function,
  • the argument is not nullable,
  • the argument accepts at least one scalar type (one of bool, int, float, or string),
  • coercive typing mode is used, i.e. strict_types=1 is not enabled,

then

  • in PHP < 8.1 the null value will be silently coerced to either false, 0, 0.0 or “”.
  • in PHP >= 8.1 a deprecation error is thrown, but the value is still coerced and the call still takes place.
  • in PHP >= 9.0 a TypeError is thrown, consistent with the behavior of user-defined functions.

Backward Incompatible Changes

Passing null to non-nullable scalar internal arguments will be forbidden in the future, which constitutes a backwards compatibility break. The behavior for user-defined functions, strict typing mode and non-scalar arguments is not affected, as all these cases already generate a TypeError for null arguments.

The following shows typical ways to resolve a deprecation warning:

// Throws deprecation warning if $maybe_null is null.
strlen($maybe_null);
 
// Resolution 1: Explicitly check for null, take different control flow path.
if (null === $maybe_null) {
    return; // or similar
}
strlen($maybe_null);
 
// Resolution 2: Explicitly specify a default value for null values.
strlen($maybe_null ?? '');
 
// Resolution 3: Explicitly cast the argument.
strlen((string) $maybe_null);

Vote

Voting started 2021-01-26 and ended on 2021-02-09.

Vote: Deprecate passing null to non-nullable arguments of internal functions? — Yes: 46 · No: 0 (closed)