@@ -1194,28 +1194,69 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop
1194
1194
return zend_string_copy (name );
1195
1195
}
1196
1196
1197
+ static zend_string * resolve_intersection_type (zend_type_list * intersection_type_list , zend_class_entry * scope )
1198
+ {
1199
+ zend_type * single_type ;
1200
+ zend_string * str = NULL ;
1201
+
1202
+ ZEND_TYPE_LIST_FOREACH (intersection_type_list , single_type ) {
1203
+ if (ZEND_TYPE_HAS_CE (* single_type )) {
1204
+ str = add_type_string (str , ZEND_TYPE_CE (* single_type )-> name , /* is_intersection */ true);
1205
+ } else {
1206
+ if (ZEND_TYPE_HAS_CE_CACHE (* single_type )
1207
+ && ZEND_TYPE_CE_CACHE (* single_type )) {
1208
+ zend_class_entry * ce = ZEND_TYPE_CE_CACHE (* single_type );
1209
+
1210
+ // TODO Can this happen?
1211
+ if (ce -> ce_flags & ZEND_ACC_ANON_CLASS ) {
1212
+ zend_string * tmp = zend_string_init (ZSTR_VAL (ce -> name ), strlen (ZSTR_VAL (ce -> name )), 0 );
1213
+ str = add_type_string (str , tmp , /* is_intersection */ true);
1214
+ } else {
1215
+ str = add_type_string (str , ce -> name , /* is_intersection */ true);
1216
+ }
1217
+ } else {
1218
+ zend_string * resolved = resolve_class_name (ZEND_TYPE_NAME (* single_type ), scope );
1219
+ str = add_type_string (str , resolved , /* is_intersection */ true);
1220
+ zend_string_release (resolved );
1221
+ }
1222
+ }
1223
+ } ZEND_TYPE_LIST_FOREACH_END ();
1224
+
1225
+ return str ;
1226
+ }
1227
+
1197
1228
zend_string * zend_type_to_string_resolved (zend_type type , zend_class_entry * scope ) {
1198
1229
zend_string * str = NULL ;
1199
1230
1200
- if (ZEND_TYPE_HAS_LIST (type )) {
1231
+ /* Pure intersection type */
1232
+ if (ZEND_TYPE_HAS_INTERSECTION (type )) {
1233
+ str = resolve_intersection_type (ZEND_TYPE_LIST (type ), scope );
1234
+ }
1235
+
1236
+ if (ZEND_TYPE_HAS_UNION (type )) {
1201
1237
zend_type * list_type ;
1202
- bool is_intersection = ZEND_TYPE_HAS_INTERSECTION (type );
1203
1238
ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (type ), list_type ) {
1239
+ /* Type within the union is an intersection */
1240
+ if (ZEND_TYPE_HAS_INTERSECTION (* list_type )) {
1241
+ str = resolve_intersection_type (ZEND_TYPE_LIST (* list_type ), scope );
1242
+ continue ;
1243
+ }
1244
+
1204
1245
if (ZEND_TYPE_HAS_CE (* list_type )) {
1205
- str = add_type_string (str , ZEND_TYPE_CE (* list_type )-> name , is_intersection );
1246
+ str = add_type_string (str , ZEND_TYPE_CE (* list_type )-> name , /* is_intersection */ false );
1206
1247
} else {
1207
1248
if (ZEND_TYPE_HAS_CE_CACHE (* list_type )
1208
1249
&& ZEND_TYPE_CE_CACHE (* list_type )) {
1209
1250
zend_class_entry * ce = ZEND_TYPE_CE_CACHE (* list_type );
1210
1251
if (ce -> ce_flags & ZEND_ACC_ANON_CLASS ) {
1211
1252
zend_string * tmp = zend_string_init (ZSTR_VAL (ce -> name ), strlen (ZSTR_VAL (ce -> name )), 0 );
1212
- str = add_type_string (str , tmp , is_intersection );
1253
+ str = add_type_string (str , tmp , /* is_intersection */ false );
1213
1254
} else {
1214
- str = add_type_string (str , ce -> name , is_intersection );
1255
+ str = add_type_string (str , ce -> name , /* is_intersection */ false );
1215
1256
}
1216
1257
} else {
1217
1258
zend_string * resolved = resolve_class_name (ZEND_TYPE_NAME (* list_type ), scope );
1218
- str = add_type_string (str , resolved , is_intersection );
1259
+ str = add_type_string (str , resolved , /* is_intersection */ false );
1219
1260
zend_string_release (resolved );
1220
1261
}
1221
1262
}
@@ -6232,8 +6273,17 @@ static zend_type zend_compile_typename(
6232
6273
6233
6274
for (uint32_t i = 0 ; i < list -> children ; i ++ ) {
6234
6275
zend_ast * type_ast = list -> child [i ];
6235
- zend_type single_type = zend_compile_single_typename (type_ast );
6236
- uint32_t single_type_mask = ZEND_TYPE_PURE_MASK (single_type );
6276
+ zend_type single_type ;
6277
+ uint32_t single_type_mask ;
6278
+
6279
+ if (type_ast -> kind == ZEND_AST_TYPE_INTERSECTION ) {
6280
+ single_type = zend_compile_typename (type_ast , false);
6281
+ type_list -> types [type_list -> num_types ++ ] = single_type ;
6282
+ continue ;
6283
+ }
6284
+
6285
+ single_type = zend_compile_single_typename (type_ast );
6286
+ single_type_mask = ZEND_TYPE_PURE_MASK (single_type );
6237
6287
6238
6288
if (single_type_mask == MAY_BE_ANY ) {
6239
6289
zend_error_noreturn (E_COMPILE_ERROR , "Type mixed can only be used as a standalone type" );
@@ -6320,13 +6370,12 @@ static zend_type zend_compile_typename(
6320
6370
}
6321
6371
zend_string_release_ex (standard_type_str , false);
6322
6372
6323
- /* Inform that the type is part of an intersection type */
6324
- ZEND_TYPE_FULL_MASK (single_type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6325
-
6326
6373
if (!ZEND_TYPE_HAS_CLASS (type )) {
6327
6374
/* The first class type can be stored directly as the type ptr payload. */
6328
6375
ZEND_TYPE_SET_PTR (type , ZEND_TYPE_NAME (single_type ));
6329
6376
ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_NAME_BIT ;
6377
+ /* Inform that the type list is an intersection type */
6378
+ ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6330
6379
} else {
6331
6380
if (type_list -> num_types == 0 ) {
6332
6381
/* Switch from single name to name list. */
@@ -6356,8 +6405,6 @@ static zend_type zend_compile_typename(
6356
6405
memcpy (list , type_list , ZEND_TYPE_LIST_SIZE (type_list -> num_types ));
6357
6406
ZEND_TYPE_SET_LIST (type , list );
6358
6407
ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_ARENA_BIT ;
6359
- /* Inform that the type list contains an intersection type */
6360
- ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6361
6408
}
6362
6409
6363
6410
free_alloca (type_list , use_heap );
0 commit comments