@@ -2198,7 +2198,12 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c,
21982198}
21992199/* }}} */
22002200
2201- // TODO Merge with the one in zend_compile
2201+ // TODO Merge with the ones in zend_compile
2202+ static void zend_bound_types_ht_dtor (zval * ptr ) {
2203+ HashTable * interface_bound_types = Z_PTR_P (ptr );
2204+ zend_hash_destroy (interface_bound_types );
2205+ efree (interface_bound_types );
2206+ }
22022207static void zend_types_ht_dtor (zval * ptr ) {
22032208 zend_type * type = Z_PTR_P (ptr );
22042209 // TODO Figure out persistency?
@@ -2207,46 +2212,66 @@ static void zend_types_ht_dtor(zval *ptr) {
22072212}
22082213
22092214ZEND_ATTRIBUTE_NONNULL static void bind_generic_types_for_inherited_interfaces (zend_class_entry * ce , const zend_class_entry * iface ) {
2210- zend_string * iface_lc_name = zend_string_tolower (iface -> name );
2211- const HashTable * ce_bound_types = ce -> bound_types ? zend_hash_find_ptr (ce -> bound_types , iface_lc_name ) : NULL ;
2212- for (uint32_t i = 0 ; i < iface -> num_interfaces ; i ++ ) {
2213- const zend_class_entry * inherited_iface = iface -> interfaces [i ];
2214- /* Bind generic types */
2215- /* We need to propagate the bound generic parameters to the inherited interfaces */
2216- if (inherited_iface -> num_generic_parameters == 0 ) {
2217- continue ;
2215+ const HashTable * iface_bound_types = iface -> bound_types ;
2216+ if (iface_bound_types == NULL ) {
2217+ #ifdef ZEND_DEBUG
2218+ for (uint32_t i = 0 ; i < iface -> num_interfaces ; i ++ ) {
2219+ const zend_class_entry * inherited_iface = iface -> interfaces [i ];
2220+ ZEND_ASSERT (inherited_iface -> num_generic_parameters == 0 );
22182221 }
2219- zend_string * inherited_iface_lc_name = zend_string_tolower (inherited_iface -> name );
2220- const HashTable * interface_bound_types = zend_hash_find_ptr (iface -> bound_types , inherited_iface_lc_name );
2221- HashTable * ce_bound_types_to_inherited_iface = zend_hash_find_ptr (ce -> bound_types , inherited_iface_lc_name );
2222- ZEND_ASSERT (interface_bound_types != NULL && "This must exist at this point" );
2223- if (ce_bound_types_to_inherited_iface == NULL ) {
2224- ALLOC_HASHTABLE (ce_bound_types_to_inherited_iface );
2225- zend_hash_init (ce_bound_types_to_inherited_iface , inherited_iface -> num_generic_parameters , NULL , zend_types_ht_dtor , false /* todo depend on internal or not */ );
2226- zend_hash_add_new_ptr (ce -> bound_types , inherited_iface_lc_name , ce_bound_types_to_inherited_iface );
2227- }
2228- for (
2229- uint32_t inherited_iface_generic_param_index = 0 ;
2230- inherited_iface_generic_param_index < inherited_iface -> num_generic_parameters ;
2231- inherited_iface_generic_param_index ++
2232- ) {
2233- const zend_generic_parameter * inherited_generic_parameter = & inherited_iface -> generic_parameters [inherited_iface_generic_param_index ];
2234- const zend_type * iface_bound_type_ptr = zend_hash_index_find_ptr (interface_bound_types , inherited_iface_generic_param_index );
2235- ZEND_ASSERT (iface_bound_type_ptr != NULL );
2236- zend_type bound_type ;
2237- if (ZEND_TYPE_IS_ASSOCIATED (* iface_bound_type_ptr )) {
2238- memcpy (& bound_type , zend_hash_find_ptr (ce_bound_types , ZEND_TYPE_NAME (* iface_bound_type_ptr )), sizeof (zend_type ));
2222+ #endif
2223+ return ;
2224+ }
2225+
2226+ if (ce -> bound_types == NULL ) {
2227+ ALLOC_HASHTABLE (ce -> bound_types );
2228+ zend_hash_init (ce -> bound_types , zend_hash_num_elements (iface_bound_types ), NULL , zend_bound_types_ht_dtor , false /* todo depend on internal or not */ );
2229+ }
2230+ const HashTable * ce_bound_types_for_direct_iface = zend_hash_find_ptr_lc (ce -> bound_types , iface -> name );
2231+
2232+ zend_string * lc_inherited_iface_name = NULL ;
2233+ const HashTable * interface_bound_types_for_inherited_iface = NULL ;
2234+ ZEND_HASH_FOREACH_STR_KEY_PTR (iface_bound_types , lc_inherited_iface_name , interface_bound_types_for_inherited_iface ) {
2235+ ZEND_ASSERT (lc_inherited_iface_name != NULL );
2236+
2237+ zend_string * generic_param_name = NULL ;
2238+ zend_ulong generic_param_index = 0 ;
2239+ zend_type * bound_type_ptr = NULL ;
2240+ HashTable * ce_bound_types_for_inherited_iface = NULL ;
2241+ ALLOC_HASHTABLE (ce_bound_types_for_inherited_iface );
2242+ zend_hash_init (
2243+ ce_bound_types_for_inherited_iface ,
2244+ zend_hash_num_elements (interface_bound_types_for_inherited_iface ),
2245+ NULL ,
2246+ zend_types_ht_dtor ,
2247+ false /* TODO depends on internals */
2248+ );
2249+ ZEND_HASH_FOREACH_KEY_PTR (interface_bound_types_for_inherited_iface , generic_param_index , generic_param_name , bound_type_ptr ) {
2250+ zend_type bound_type = * bound_type_ptr ;
2251+ if (ZEND_TYPE_IS_ASSOCIATED (bound_type )) {
2252+ ZEND_ASSERT (ce_bound_types_for_direct_iface != NULL &&
2253+ "If a bound type is generic then we must have bound types for the current interface" );
2254+ // TODO Resolve
2255+ const zend_type * ce_bound_type_ptr = zend_hash_find_ptr (ce_bound_types_for_direct_iface , ZEND_TYPE_NAME (bound_type ));
2256+ ZEND_ASSERT (ce_bound_type_ptr != NULL );
2257+ bound_type = * ce_bound_type_ptr ;
2258+ }
2259+
2260+ zend_type_copy_ctor (& bound_type , true, false /* TODO Depends on internal or not? */ );
2261+ if (generic_param_name ) {
2262+ zend_hash_add_mem (ce_bound_types_for_inherited_iface , generic_param_name ,
2263+ & bound_type , sizeof (bound_type ));
22392264 } else {
2240- bound_type = * iface_bound_type_ptr ;
2265+ zend_hash_index_add_mem (ce_bound_types_for_inherited_iface , generic_param_index ,
2266+ & bound_type , sizeof (bound_type ));
22412267 }
2242- /* Deep type copy */
2243- zend_type_copy_ctor (& bound_type , true, false);
2244- zend_hash_add_mem (ce_bound_types_to_inherited_iface , inherited_generic_parameter -> name ,
2245- & bound_type , sizeof (bound_type ));
2246- }
2247- zend_string_release_ex (inherited_iface_lc_name , false);
2248- }
2249- zend_string_release_ex (iface_lc_name , false);
2268+ } ZEND_HASH_FOREACH_END ();
2269+
2270+ // TODO Check we don't already have the bound types for the inherited CE
2271+ //HashTable *
2272+
2273+ zend_hash_add_new_ptr (ce -> bound_types , lc_inherited_iface_name , ce_bound_types_for_inherited_iface );
2274+ } ZEND_HASH_FOREACH_END ();
22502275}
22512276
22522277static void do_interface_implementation (zend_class_entry * ce , zend_class_entry * iface ) /* {{{ */
@@ -2334,9 +2359,6 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry *
23342359 zend_string_release (constraint_type_str );
23352360 return ;
23362361 }
2337- ///* Bind our generic type (the key) to the generic iface type */
2338- //zend_type iface_generic_type = (zend_type) ZEND_TYPE_INIT_CLASS(zend_string_copy(generic_parameter->name), /* allow null */ false, _ZEND_TYPE_ASSOCIATED_BIT);
2339- //zend_hash_add_mem(bound_types, current_generic_param_name, &iface_generic_type, sizeof(iface_generic_type));
23402362 break ;
23412363 }
23422364 } else {
@@ -2354,14 +2376,14 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry *
23542376 zend_string_release (constraint_type_str );
23552377 return ;
23562378 }
2357- /* Change key from index to generic parameter name */
2358- /* Deep type copy */
2359- zend_type bound_type = * bound_type_ptr ;
2360- zend_type_copy_ctor (& bound_type , true, false);
2361- zend_hash_add_mem (bound_types , generic_parameter -> name ,
2362- & bound_type , sizeof (bound_type ));
2363- //zend_hash_index_del(bound_types, i);
23642379 }
2380+ /* Deep type copy */
2381+ zend_type bound_type = * bound_type_ptr ;
2382+ zend_type_copy_ctor (& bound_type , true, false);
2383+ zend_hash_add_mem (bound_types , generic_parameter -> name ,
2384+ & bound_type , sizeof (bound_type ));
2385+ ///* Should we change the key from index to generic parameter name? */
2386+ //zend_hash_index_del(bound_types, i);
23652387 }
23662388 }
23672389 bind_generic_types_for_inherited_interfaces (ce , iface );
0 commit comments