@@ -739,9 +739,21 @@ static const zend_class_entry *resolve_single_class_type(
739739 zend_string * name ,
740740 const zend_class_entry * scope ) {
741741 if (zend_string_equals_ci (name , ZSTR_KNOWN (ZEND_STR_SELF ))) {
742+ /* We don't fetch the scope in the ZEND_VERIFY_RETURN_TYPE VM opcode, thus fetch it here
743+ * This is an OK tradeoff as for class methods self/parent types are resolved at compile time
744+ * Therefore, we only hit this for trait methods and unbound closures */
745+ if (!scope ) {
746+ scope = zend_get_executed_scope ();
747+ }
742748 /* If we don't have a scope, returning the NULL pointer is fine as the error handling is done on the call site */
743749 return scope ;
744- } else if (UNEXPECTED (zend_string_equals_ci (name , ZSTR_KNOWN (ZEND_STR_PARENT )))) { // Parent as a type is extremely uncommon
750+ } else if (UNEXPECTED (zend_string_equals_ci (name , ZSTR_KNOWN (ZEND_STR_PARENT )))) { /* Parent as a type is extremely uncommon */
751+ /* We don't fetch the scope in the ZEND_VERIFY_RETURN_TYPE VM opcode, thus fetch it here
752+ * This is an OK tradeoff as for class methods self/parent types are resolved at compile time
753+ * Therefore, we only hit this for trait methods and unbound closures */
754+ if (!scope ) {
755+ scope = zend_get_executed_scope ();
756+ }
745757 return scope ? scope -> parent : NULL ;
746758 } else {
747759 return zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT );
@@ -894,14 +906,18 @@ static zend_type_check_status zend_check_type_slow(
894906 zend_is_callable (arg , callable_check_flag , NULL )) {
895907 return ZEND_TYPE_CHECK_VALID ;
896908 }
897- /* TODO: move to return type check? */
909+
910+ /* Although static is most commonly used as a return type, it can also be used as a class constant type */
898911 if (
899- (type_mask & MAY_BE_STATIC )
900- && scope != NULL
912+ (ZEND_TYPE_FULL_MASK (* type ) & MAY_BE_STATIC )
901913 && Z_TYPE_P (arg ) == IS_OBJECT
902- && instanceof_function (Z_OBJCE_P (arg ), scope )
903914 ) {
904- return ZEND_TYPE_CHECK_VALID ;
915+ if (!scope ) {
916+ scope = zend_get_called_scope (EG (current_execute_data ));
917+ }
918+ if (EXPECTED (scope ) && instanceof_function (Z_OBJCE_P (arg ), scope )) {
919+ return ZEND_TYPE_CHECK_VALID ;
920+ }
905921 }
906922
907923 /* Only scalar types may coerce to other scalar types */
@@ -985,6 +1001,15 @@ static bool zend_check_type_and_coerce_slow(
9851001 return status != ZEND_TYPE_CHECK_INVALID ;
9861002}
9871003
1004+ static bool zend_check_return_type_slow (
1005+ const zend_type * type ,
1006+ zval * arg ,
1007+ const zend_reference * ref
1008+ ) {
1009+ bool strict_types = ZEND_RET_USES_STRICT_TYPES () || (ref && ZEND_REF_HAS_TYPE_SOURCES (ref ));
1010+ return zend_check_type_and_coerce (type , arg , NULL , strict_types , 0 );
1011+ }
1012+
9881013ZEND_API bool zend_check_user_type_slow (
9891014 const zend_type * type , zval * arg , const zend_reference * ref , bool is_return_type )
9901015{
0 commit comments