@@ -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 );
@@ -899,14 +911,18 @@ static zend_type_check_status zend_check_type_slow(
899911 zend_is_callable (arg , callable_check_flag , NULL )) {
900912 return ZEND_TYPE_CHECK_VALID ;
901913 }
902- /* TODO: move to return type check? */
914+
915+ /* Although static is most commonly used as a return type, it can also be used as a class constant type */
903916 if (
904- (type_mask & MAY_BE_STATIC )
905- && scope != NULL
917+ (ZEND_TYPE_FULL_MASK (* type ) & MAY_BE_STATIC )
906918 && Z_TYPE_P (arg ) == IS_OBJECT
907- && instanceof_function (Z_OBJCE_P (arg ), scope )
908919 ) {
909- return ZEND_TYPE_CHECK_VALID ;
920+ if (!scope ) {
921+ scope = zend_get_called_scope (EG (current_execute_data ));
922+ }
923+ if (EXPECTED (scope ) && instanceof_function (Z_OBJCE_P (arg ), scope )) {
924+ return ZEND_TYPE_CHECK_VALID ;
925+ }
910926 }
911927
912928 /* Only scalar types may coerce to other scalar types */
@@ -990,6 +1006,15 @@ static bool zend_check_type_and_coerce_slow(
9901006 return status != ZEND_TYPE_CHECK_INVALID ;
9911007}
9921008
1009+ static bool zend_check_return_type_slow (
1010+ const zend_type * type ,
1011+ zval * arg ,
1012+ const zend_reference * ref
1013+ ) {
1014+ bool strict_types = ZEND_RET_USES_STRICT_TYPES () || (ref && ZEND_REF_HAS_TYPE_SOURCES (ref ));
1015+ return zend_check_type_and_coerce (type , arg , NULL , strict_types , 0 );
1016+ }
1017+
9931018ZEND_API bool zend_check_user_type_slow (
9941019 const zend_type * type , zval * arg , const zend_reference * ref , bool is_return_type )
9951020{
0 commit comments