Commit f1c6357363e for php.net

commit f1c6357363e6209184fb60ba1d0d5ad4bcb8d358
Author: Tim Düsterhus <tim@tideways-gmbh.com>
Date:   Sat May 16 18:20:07 2026 +0200

    Deprecate making `__debugInfo()` nullable (#21984)

    * Deprecate making `__debugInfo()` nullable

    Returning `null` is already deprecated since PHP 8.5
    (3dc962b9f765f5f4a7f8c4fa93f55fee8dad84ca). Not deprecating a corresponding
    return type seems like an oversight.

    * NEWS / UPGRADING

diff --git a/NEWS b/NEWS
index 821dc09ad3a..65b1f85ba37 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ PHP                                                                        NEWS
     initialization). (Arnaud)
   . Enabled the TAILCALL VM on Windows when compiling with Clang >= 19 x86_64.
     (henderkes)
+  . Deprecate specifying a nullable return type for __debugInfo(). (timwolla)

 - BCMath:
   . Added NUL-byte validation to BCMath functions. (jorgsowa)
diff --git a/UPGRADING b/UPGRADING
index 37abc121a07..de086c600f5 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -189,6 +189,10 @@ PHP 8.6 UPGRADE NOTES
 4. Deprecated Functionality
 ========================================

+- Core:
+  . Specifying a return type of array|null / ?array for __debugInfo() is now
+    deprecated. Specify array instead.
+
 - GMP
   . The shift (<<, >>) and exponentiation (**) operators on GMP objects now
     emit a deprecation warning when converting a float right operand to int
diff --git a/Zend/tests/debug_info/debug_info.phpt b/Zend/tests/debug_info/debug_info.phpt
index bff5876777b..e7bb4d48aec 100644
--- a/Zend/tests/debug_info/debug_info.phpt
+++ b/Zend/tests/debug_info/debug_info.phpt
@@ -21,6 +21,12 @@ public function __debugInfo() {
   }
 }

+class Baz {
+  public function __debugInfo(): ?array {
+    return null;
+  }
+}
+
 $f = new Foo;
 var_dump($f);

@@ -28,6 +34,7 @@ public function __debugInfo() {
 var_dump($b);
 ?>
 --EXPECTF--
+Deprecated: Returning null from Baz::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead in %s on line %d
 object(Foo)#%d (3) {
   ["a"]=>
   int(1)
diff --git a/Zend/tests/magic_methods/magic_methods_inheritance_rules.phpt b/Zend/tests/magic_methods/magic_methods_inheritance_rules.phpt
index 6bdcafb1bfb..a4076ee00ce 100644
--- a/Zend/tests/magic_methods/magic_methods_inheritance_rules.phpt
+++ b/Zend/tests/magic_methods/magic_methods_inheritance_rules.phpt
@@ -66,5 +66,6 @@ public function __unset(string|array $name): void {}

 echo 'No problems!';
 ?>
---EXPECT--
+--EXPECTF--
+Deprecated: Returning null from ValidMagicMethods::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead in %s on line %d
 No problems!
diff --git a/Zend/tests/return_types/042.phpt b/Zend/tests/return_types/042.phpt
index 069e0228ff9..21483047d4f 100644
--- a/Zend/tests/return_types/042.phpt
+++ b/Zend/tests/return_types/042.phpt
@@ -20,5 +20,10 @@ public function __debugInfo(): array {}

 echo 'No problems!';
 ?>
---EXPECT--
+--EXPECTF--
+Deprecated: Returning null from UnionType::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead in %s on line %d
+
+Deprecated: Returning null from UnionType2::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead in %s on line %d
+
+Deprecated: Returning null from UnionTypeOldStyle::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead in %s on line %d
 No problems!
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 004b4fd81e9..65834adbaff 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -2825,6 +2825,10 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
 		zend_check_magic_method_non_static(ce, fptr, error_type);
 		zend_check_magic_method_public(ce, fptr);
 		zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
+		if ((fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & MAY_BE_NULL) {
+			zend_error(E_DEPRECATED, "Returning null from %s::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead",
+				ZSTR_VAL(ce->name));
+		}
 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
 		zend_check_magic_method_args(0, ce, fptr, error_type);
 		zend_check_magic_method_non_static(ce, fptr, error_type);
diff --git a/ext/simplexml/simplexml.stub.php b/ext/simplexml/simplexml.stub.php
index 935af16621e..6faf873c885 100644
--- a/ext/simplexml/simplexml.stub.php
+++ b/ext/simplexml/simplexml.stub.php
@@ -51,7 +51,7 @@ public function getName(): string {}

     public function __toString(): string {}

-    public function __debugInfo(): ?array {}
+    public function __debugInfo(): array {}

     /** @tentative-return-type */
     public function count(): int {}
diff --git a/ext/simplexml/simplexml_arginfo.h b/ext/simplexml/simplexml_arginfo.h
index 419c7874fbc..5a62efbc7be 100644
Binary files a/ext/simplexml/simplexml_arginfo.h and b/ext/simplexml/simplexml_arginfo.h differ