@@ -478,14 +478,6 @@ static inheritance_status zend_do_perform_implementation_check(
478
478
}
479
479
}
480
480
481
- /*
482
- if (status == INHERITANCE_UNRESOLVED && CG(unverified_types)) {
483
- zend_string *key = zend_string_tolower(fe->common.scope->name);
484
- zend_hash_add_empty_element(CG(unverified_types), key);
485
- zend_string_release(key);
486
- }
487
- */
488
-
489
481
return status ;
490
482
}
491
483
/* }}} */
@@ -651,6 +643,21 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function
651
643
}
652
644
/* }}} */
653
645
646
+ static zend_bool lsp_fail_is_error (zend_function * child , zend_function * parent ) {
647
+ /* Failed verification against abstract method, error. */
648
+ if (child -> common .prototype && (child -> common .prototype -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
649
+ return 1 ;
650
+ }
651
+ /* Failed return type verification, error. */
652
+ if ((parent -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) &&
653
+ !check_inherited_return_type (child , child -> common .arg_info - 1 , parent , parent -> common .arg_info - 1 )) {
654
+ return 1 ;
655
+ }
656
+
657
+ /* Legacy: Parameter verification failures against non-abstract methods are only warnings. */
658
+ return 0 ;
659
+ }
660
+
654
661
static zend_always_inline uint32_t func_lineno (zend_function * fn ) {
655
662
return fn -> common .type == ZEND_USER_FUNCTION ? fn -> op_array .line_start : 0 ;
656
663
}
@@ -737,31 +744,31 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
737
744
ZEND_FN_SCOPE_NAME (child ), ZSTR_VAL (child -> common .function_name ), zend_visibility_string (parent_flags ), ZEND_FN_SCOPE_NAME (parent ), (parent_flags & ZEND_ACC_PUBLIC ) ? "" : " or weaker" );
738
745
}
739
746
740
- if (UNEXPECTED (zend_do_perform_implementation_check (child , parent )) == INHERITANCE_ERROR ) {
741
- int error_level ;
742
- const char * error_verb ;
743
- zend_string * method_prototype = zend_get_function_declaration (parent );
744
- zend_string * child_prototype = zend_get_function_declaration (child );
745
-
746
- if (child -> common .prototype && (
747
- child -> common .prototype -> common .fn_flags & ZEND_ACC_ABSTRACT
748
- )) {
749
- error_level = E_COMPILE_ERROR ;
750
- error_verb = "must" ;
751
- } else if ((parent -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) &&
752
- !check_inherited_return_type (child , child -> common .arg_info - 1 , parent , parent -> common .arg_info - 1 )) {
753
- error_level = E_COMPILE_ERROR ;
754
- error_verb = "must" ;
747
+ inheritance_status status = zend_do_perform_implementation_check (child , parent );
748
+ if (UNEXPECTED (status == INHERITANCE_ERROR )) {
749
+ if (lsp_fail_is_error (child , parent )) {
750
+ zend_string * method_prototype = zend_get_function_declaration (parent );
751
+ zend_string * child_prototype = zend_get_function_declaration (child );
752
+ zend_error_at (E_COMPILE_ERROR , NULL , func_lineno (child ),
753
+ "Declaration of %s must be compatible with %s" ,
754
+ ZSTR_VAL (child_prototype ), ZSTR_VAL (method_prototype ));
755
+ zend_string_efree (child_prototype );
756
+ zend_string_efree (method_prototype );
755
757
} else {
756
- error_level = E_WARNING ;
757
- error_verb = "should" ;
758
+ /* Delay this warning until runtime, to avoid duplicate warnings. */
759
+ status = INHERITANCE_UNRESOLVED ;
758
760
}
759
- zend_error_at (error_level , NULL , func_lineno (child ),
760
- "Declaration of %s %s be compatible with %s" ,
761
- ZSTR_VAL (child_prototype ), error_verb , ZSTR_VAL (method_prototype ));
762
- zend_string_efree (child_prototype );
763
- zend_string_efree (method_prototype );
764
761
}
762
+
763
+ /* TODO Properly handle UNRESOLVED. */
764
+
765
+ /*
766
+ if (status == INHERITANCE_UNRESOLVED && CG(unverified_types)) {
767
+ zend_string *key = zend_string_tolower(fe->common.scope->name);
768
+ zend_hash_add_empty_element(CG(unverified_types), key);
769
+ zend_string_release(key);
770
+ }
771
+ */
765
772
}
766
773
} while (0 );
767
774
}
@@ -2256,9 +2263,7 @@ ZEND_API void zend_verify_variance(zend_class_entry *ce)
2256
2263
inheritance_status status = check_inherited_return_type (
2257
2264
child , & child -> common .arg_info [-1 ],
2258
2265
parent , & parent -> common .arg_info [-1 ]);
2259
- /* TODO I don't think this is right -- what if the class now exists
2260
- * but has wrong variance? */
2261
- if (status == INHERITANCE_UNRESOLVED ) {
2266
+ if (status != INHERITANCE_SUCCESS ) {
2262
2267
inheritance_runtime_error_msg (child , parent );
2263
2268
continue ;
2264
2269
}
@@ -2295,7 +2300,7 @@ ZEND_API void zend_verify_variance(zend_class_entry *ce)
2295
2300
inheritance_status status = check_inherited_parameter_type (
2296
2301
child , child_arg_info ,
2297
2302
parent , parent_arg_info );
2298
- if (status == INHERITANCE_UNRESOLVED ) {
2303
+ if (status != INHERITANCE_SUCCESS ) {
2299
2304
inheritance_runtime_error_msg (child , parent );
2300
2305
continue ;
2301
2306
}
0 commit comments