@@ -2328,61 +2328,74 @@ ZEND_ATTRIBUTE_NONNULL static void bind_generic_types_for_inherited_interfaces(z
23282328 ZEND_HASH_FOREACH_STR_KEY_PTR (iface_bound_types , lc_inherited_iface_name , interface_bound_types_for_inherited_iface ) {
23292329 ZEND_ASSERT (lc_inherited_iface_name != NULL );
23302330
2331- zend_string * generic_param_name = NULL ;
2332- zend_ulong generic_param_index = 0 ;
2333- zend_type * bound_type_ptr = NULL ;
2334- HashTable * ce_bound_types_for_inherited_iface = NULL ;
2335- ALLOC_HASHTABLE (ce_bound_types_for_inherited_iface );
2336- zend_hash_init (
2337- ce_bound_types_for_inherited_iface ,
2338- zend_hash_num_elements (interface_bound_types_for_inherited_iface ),
2339- NULL ,
2340- zend_types_ht_dtor ,
2341- false /* TODO depends on internals */
2342- );
2343- ZEND_HASH_FOREACH_KEY_PTR (interface_bound_types_for_inherited_iface , generic_param_index , generic_param_name , bound_type_ptr ) {
2344- ZEND_ASSERT (generic_param_name == NULL ); // TODO Change foreach macro;
2345- zend_type bound_type = * bound_type_ptr ;
2346- if (ZEND_TYPE_IS_GENERIC_PARAM_NAME (bound_type )) {
2347- ZEND_ASSERT (ce_bound_types_for_direct_iface != NULL &&
2348- "If a bound type is generic then we must have bound types for the current interface" );
2349- const zend_type * ce_bound_type_ptr = zend_hash_index_find_ptr (ce_bound_types_for_direct_iface , bound_type_ptr -> generic_param_index );
2350- ZEND_ASSERT (ce_bound_type_ptr != NULL );
2351- bound_type = * ce_bound_type_ptr ;
2352- }
2353-
2354- zend_type_copy_ctor (& bound_type , true, false /* TODO Depends on internal or not? */ );
2355- zend_hash_index_add_mem (ce_bound_types_for_inherited_iface , generic_param_index ,
2356- & bound_type , sizeof (bound_type ));
2357- } ZEND_HASH_FOREACH_END ();
2358-
23592331 const HashTable * existing_bound_types_for_inherited_iface = zend_hash_find_ptr (ce -> bound_types , lc_inherited_iface_name );
23602332 if (EXPECTED (existing_bound_types_for_inherited_iface == NULL )) {
2333+ HashTable * ce_bound_types_for_inherited_iface = NULL ;
2334+ ALLOC_HASHTABLE (ce_bound_types_for_inherited_iface );
2335+ zend_hash_init (
2336+ ce_bound_types_for_inherited_iface ,
2337+ zend_hash_num_elements (interface_bound_types_for_inherited_iface ),
2338+ NULL ,
2339+ zend_types_ht_dtor ,
2340+ false /* TODO depends on internals */
2341+ );
2342+
2343+ zend_ulong generic_param_index = 0 ;
2344+ const zend_type * bound_type_ptr = NULL ;
2345+ ZEND_HASH_FOREACH_NUM_KEY_PTR (interface_bound_types_for_inherited_iface , generic_param_index , bound_type_ptr ) {
2346+ zend_type bound_type = * bound_type_ptr ;
2347+ if (ZEND_TYPE_IS_GENERIC_PARAM_NAME (bound_type )) {
2348+ ZEND_ASSERT (ce_bound_types_for_direct_iface != NULL &&
2349+ "If a bound type is generic then we must have bound types for the current interface" );
2350+ const zend_type * ce_bound_type_ptr = zend_hash_index_find_ptr (ce_bound_types_for_direct_iface , bound_type_ptr -> generic_param_index );
2351+ ZEND_ASSERT (ce_bound_type_ptr != NULL );
2352+ bound_type = * ce_bound_type_ptr ;
2353+ }
2354+
2355+ zend_type_copy_ctor (& bound_type , true, false /* TODO Depends on internal or not? */ );
2356+ zend_hash_index_add_mem (ce_bound_types_for_inherited_iface , generic_param_index ,
2357+ & bound_type , sizeof (bound_type ));
2358+ } ZEND_HASH_FOREACH_END ();
2359+ zend_hash_add_new_ptr (ce -> bound_types , lc_inherited_iface_name , ce_bound_types_for_inherited_iface );
23612360 } else {
2362- zend_ulong idx ;
2363- zend_string * bound_name ;
2364- const zend_type * ptr ;
2365- ZEND_HASH_FOREACH_KEY_PTR (existing_bound_types_for_inherited_iface , idx , bound_name , ptr ) {
2366- if (bound_name != NULL ) {
2367- continue ;
2361+ const uint32_t num_generic_types = zend_hash_num_elements (interface_bound_types_for_inherited_iface );
2362+ ZEND_ASSERT (zend_hash_num_elements (existing_bound_types_for_inherited_iface ) == num_generic_types && "Existing bound types should have errored before" );
2363+
2364+ for (zend_ulong bound_type_index = 0 ; bound_type_index < num_generic_types ; bound_type_index ++ ) {
2365+ const zend_type * iface_bound_type_ptr = zend_hash_index_find_ptr (interface_bound_types_for_inherited_iface , bound_type_index );
2366+ const zend_type * ce_bound_type_ptr = zend_hash_index_find_ptr (existing_bound_types_for_inherited_iface , bound_type_index );
2367+ ZEND_ASSERT (iface_bound_type_ptr != NULL && ce_bound_type_ptr != NULL );
2368+ if (ZEND_TYPE_IS_GENERIC_PARAM_NAME (* iface_bound_type_ptr )) {
2369+ iface_bound_type_ptr = zend_hash_index_find_ptr (ce_bound_types_for_direct_iface , iface_bound_type_ptr -> generic_param_index );
2370+ ZEND_ASSERT (iface_bound_type_ptr != NULL );
23682371 }
2369- const zend_type t1 = * ptr ;
2370- const zend_type * ptr2 = zend_hash_index_find_ptr (ce_bound_types_for_inherited_iface , idx );
2371- ZEND_ASSERT (ptr2 != NULL );
2372- const zend_type t2 = * ptr2 ;
2372+ const zend_type t1 = * iface_bound_type_ptr ;
2373+ const zend_type t2 = * ce_bound_type_ptr ;
23732374 if (
23742375 ZEND_TYPE_FULL_MASK (t1 ) != ZEND_TYPE_FULL_MASK (t2 )
23752376 || (ZEND_TYPE_HAS_NAME (t1 ) && !zend_string_equals (ZEND_TYPE_NAME (t1 ), ZEND_TYPE_NAME (t2 )))
23762377 // || ZEND_TYPE_HAS_LIST(t1) && TODO Check list types are equal
23772378 ) {
2378- // TODO Improve this error message
2379- zend_error_noreturn (E_COMPILE_ERROR , "Bound types for implicitly and explicitly implemented interfaces must match" );
2379+ const zend_class_entry * inherited_iface = zend_hash_find_ptr (CG (class_table ), lc_inherited_iface_name );
2380+ ZEND_ASSERT (inherited_iface != NULL );
2381+ const zend_generic_parameter param = inherited_iface -> generic_parameters [bound_type_index ];
2382+
2383+ zend_string * ce_bound_type_str = zend_type_to_string_resolved (t2 , ce , NULL );
2384+ zend_string * iface_bound_type_str = zend_type_to_string_resolved (t1 , iface , NULL );
2385+ zend_error_noreturn (E_COMPILE_ERROR ,
2386+ "Bound type %s for interface %s implemented explicitly in %s with type %s must match the implicitly bound type %s from interface %s" ,
2387+ ZSTR_VAL (param .name ),
2388+ ZSTR_VAL (inherited_iface -> name ),
2389+ ZSTR_VAL (ce -> name ),
2390+ ZSTR_VAL (ce_bound_type_str ),
2391+ ZSTR_VAL (iface_bound_type_str ),
2392+ ZSTR_VAL (iface -> name )
2393+ );
2394+ zend_string_release_ex (ce_bound_type_str , false);
2395+ zend_string_release_ex (iface_bound_type_str , false);
23802396 }
2381- } ZEND_HASH_FOREACH_END ();
2382- /* Remove current ones as they may be incomplete without the type name binding */
2383- zend_hash_del (ce -> bound_types , lc_inherited_iface_name );
2397+ }
23842398 }
2385- zend_hash_add_new_ptr (ce -> bound_types , lc_inherited_iface_name , ce_bound_types_for_inherited_iface );
23862399 } ZEND_HASH_FOREACH_END ();
23872400}
23882401
0 commit comments