diff --git a/UPGRADING b/UPGRADING index c2aef62354064..086fb975d05df 100644 --- a/UPGRADING +++ b/UPGRADING @@ -65,6 +65,7 @@ PHP 8.5 UPGRADE NOTES ======================================== - Core: + . Closure is now a proper subtype of callable . Added support for Closures in constant expressions. RFC: https://wiki.php.net/rfc/closures_in_const_expr diff --git a/Zend/tests/type_declarations/callable_001.phpt b/Zend/tests/type_declarations/callable/callable_001.phpt similarity index 100% rename from Zend/tests/type_declarations/callable_001.phpt rename to Zend/tests/type_declarations/callable/callable_001.phpt diff --git a/Zend/tests/type_declarations/callable_002.phpt b/Zend/tests/type_declarations/callable/callable_002.phpt similarity index 100% rename from Zend/tests/type_declarations/callable_002.phpt rename to Zend/tests/type_declarations/callable/callable_002.phpt diff --git a/Zend/tests/type_declarations/callable_003.phpt b/Zend/tests/type_declarations/callable/callable_003.phpt similarity index 100% rename from Zend/tests/type_declarations/callable_003.phpt rename to Zend/tests/type_declarations/callable/callable_003.phpt diff --git a/Zend/tests/type_declarations/callable/callable_variance_closure.phpt b/Zend/tests/type_declarations/callable/callable_variance_closure.phpt new file mode 100644 index 0000000000000..d3d0a77fd9a7c --- /dev/null +++ b/Zend/tests/type_declarations/callable/callable_variance_closure.phpt @@ -0,0 +1,15 @@ +--TEST-- +Closure should be covariant with callable +--FILE-- + +OK +--EXPECT-- +OK diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 7abc8119d9ea5..d06d8e96195c5 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -23,6 +23,7 @@ #include "zend_execute.h" #include "zend_inheritance.h" #include "zend_interfaces.h" +#include "zend_closures.h" #include "zend_smart_str.h" #include "zend_operators.h" #include "zend_exceptions.h" @@ -490,6 +491,19 @@ static inheritance_status zend_is_class_subtype_of_type( } } + /* If the parent has 'callable' as a return type, then Closure satisfies the co-variant check */ + if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_CALLABLE) { + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name); + if (!fe_ce) { + have_unresolved = 1; + } else if (fe_ce == zend_ce_closure) { + track_class_dependency(fe_ce, fe_class_name); + return INHERITANCE_SUCCESS; + } else { + return INHERITANCE_ERROR; + } + } + zend_type *single_type; /* Traverse the list of parent types and check if the current child (FE)