@@ -2198,7 +2198,12 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c,
2198
2198
}
2199
2199
/* }}} */
2200
2200
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
+ }
2202
2207
static void zend_types_ht_dtor (zval * ptr ) {
2203
2208
zend_type * type = Z_PTR_P (ptr );
2204
2209
// TODO Figure out persistency?
@@ -2207,46 +2212,66 @@ static void zend_types_ht_dtor(zval *ptr) {
2207
2212
}
2208
2213
2209
2214
ZEND_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 );
2218
2221
}
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 ));
2239
2264
} 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 ));
2241
2267
}
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 ();
2250
2275
}
2251
2276
2252
2277
static 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 *
2334
2359
zend_string_release (constraint_type_str );
2335
2360
return ;
2336
2361
}
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));
2340
2362
break ;
2341
2363
}
2342
2364
} else {
@@ -2354,14 +2376,14 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry *
2354
2376
zend_string_release (constraint_type_str );
2355
2377
return ;
2356
2378
}
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);
2364
2379
}
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);
2365
2387
}
2366
2388
}
2367
2389
bind_generic_types_for_inherited_interfaces (ce , iface );
0 commit comments