@@ -1316,10 +1316,10 @@ static zend_string *add_intersection_type(zend_string *str,
1316
1316
ZEND_TYPE_LIST_FOREACH (intersection_type_list , single_type ) {
1317
1317
ZEND_ASSERT (!ZEND_TYPE_HAS_LIST (* single_type ));
1318
1318
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* single_type ));
1319
- zend_string * name = ZEND_TYPE_NAME ( * single_type );
1320
- zend_string * resolved = resolve_class_name ( name , scope );
1321
- intersection_str = add_type_string ( intersection_str , resolved , /* is_intersection */ true);
1322
- zend_string_release ( resolved );
1319
+ ZEND_ASSERT (! ZEND_TYPE_IS_RELATIVE_SELF ( * single_type ) && "Compile time disallowed to have 'self' in intersection" );
1320
+ ZEND_ASSERT (! ZEND_TYPE_IS_RELATIVE_PARENT ( * single_type ) && "Compile time disallowed to have 'parent' in intersection" );
1321
+
1322
+ intersection_str = add_type_string ( intersection_str , ZEND_TYPE_NAME ( * single_type ), /* is_intersection */ true );
1323
1323
} ZEND_TYPE_LIST_FOREACH_END ();
1324
1324
1325
1325
ZEND_ASSERT (intersection_str );
@@ -1351,13 +1351,30 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
1351
1351
}
1352
1352
ZEND_ASSERT (!ZEND_TYPE_HAS_LIST (* list_type ));
1353
1353
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* list_type ));
1354
- zend_string * name = ZEND_TYPE_NAME (* list_type );
1355
- zend_string * resolved = resolve_class_name (name , scope );
1356
- str = add_type_string (str , resolved , /* is_intersection */ false);
1357
- zend_string_release (resolved );
1354
+
1355
+ /* We already have resolved types from compile time
1356
+ * Mimic unresolved types for BC with "self" and "parent" */
1357
+ if (!scope && ZEND_TYPE_IS_RELATIVE_SELF (* list_type )) {
1358
+ str = add_type_string (str , ZSTR_KNOWN (ZEND_STR_SELF ), /* is_intersection */ false);
1359
+ } else if (!scope && ZEND_TYPE_IS_RELATIVE_PARENT (* list_type )) {
1360
+ str = add_type_string (str , ZSTR_KNOWN (ZEND_STR_PARENT ), /* is_intersection */ false);
1361
+ } else {
1362
+ zend_string * name = ZEND_TYPE_NAME (* list_type );
1363
+ zend_string * resolved = resolve_class_name (name , scope );
1364
+ str = add_type_string (str , resolved , /* is_intersection */ false);
1365
+ zend_string_release (resolved );
1366
+ }
1358
1367
} ZEND_TYPE_LIST_FOREACH_END ();
1359
1368
} else if (ZEND_TYPE_HAS_NAME (type )) {
1360
- str = resolve_class_name (ZEND_TYPE_NAME (type ), scope );
1369
+ /* We already have resolved types from compile time
1370
+ * Mimic unresolved types for BC with "self" and "parent" */
1371
+ if (!scope && ZEND_TYPE_IS_RELATIVE_SELF (type )) {
1372
+ str = ZSTR_KNOWN (ZEND_STR_SELF );
1373
+ } else if (!scope && ZEND_TYPE_IS_RELATIVE_PARENT (type )) {
1374
+ str = ZSTR_KNOWN (ZEND_STR_PARENT );
1375
+ } else {
1376
+ str = resolve_class_name (ZEND_TYPE_NAME (type ), scope );
1377
+ }
1361
1378
}
1362
1379
1363
1380
uint32_t type_mask = ZEND_TYPE_PURE_MASK (type );
@@ -6361,14 +6378,14 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
6361
6378
6362
6379
return (zend_type ) ZEND_TYPE_INIT_CODE (ast -> attr , 0 , 0 );
6363
6380
} else {
6364
- zend_string * class_name = zend_ast_get_str (ast );
6365
- uint8_t type_code = zend_lookup_builtin_type_by_name (class_name );
6381
+ zend_string * type_name = zend_ast_get_str (ast );
6382
+ uint8_t type_code = zend_lookup_builtin_type_by_name (type_name );
6366
6383
6367
6384
if (type_code != 0 ) {
6368
6385
if ((ast -> attr & ZEND_NAME_NOT_FQ ) != ZEND_NAME_NOT_FQ ) {
6369
6386
zend_error_noreturn (E_COMPILE_ERROR ,
6370
6387
"Type declaration '%s' must be unqualified" ,
6371
- ZSTR_VAL (zend_string_tolower (class_name )));
6388
+ ZSTR_VAL (zend_string_tolower (type_name )));
6372
6389
}
6373
6390
6374
6391
/* Transform iterable into a type union alias */
@@ -6382,38 +6399,58 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
6382
6399
return (zend_type ) ZEND_TYPE_INIT_CODE (type_code , 0 , 0 );
6383
6400
} else {
6384
6401
const char * correct_name ;
6385
- zend_string * orig_name = zend_ast_get_str (ast );
6386
6402
uint32_t fetch_type = zend_get_class_fetch_type_ast (ast );
6403
+ uint32_t type_flags = 0 ;
6404
+ zend_string * class_name = type_name ;
6405
+
6387
6406
if (fetch_type == ZEND_FETCH_CLASS_DEFAULT ) {
6388
6407
class_name = zend_resolve_class_name_ast (ast );
6389
6408
zend_assert_valid_class_name (class_name );
6390
6409
} else {
6410
+ ZEND_ASSERT (fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT );
6411
+
6391
6412
zend_ensure_valid_class_fetch_type (fetch_type );
6413
+ if (fetch_type == ZEND_FETCH_CLASS_SELF ) {
6414
+ type_flags = _ZEND_TYPE_SELF_BIT ;
6415
+ /* Scope might be unknown for unbound closures and traits */
6416
+ if (zend_is_scope_known ()) {
6417
+ class_name = CG (active_class_entry )-> name ;
6418
+ ZEND_ASSERT (class_name && "must know class name when resolving self type at compile time" );
6419
+ }
6420
+ } else {
6421
+ ZEND_ASSERT (fetch_type == ZEND_FETCH_CLASS_PARENT );
6422
+ type_flags = _ZEND_TYPE_PARENT_BIT ;
6423
+ /* Scope might be unknown for unbound closures and traits */
6424
+ if (zend_is_scope_known ()) {
6425
+ class_name = CG (active_class_entry )-> parent_name ;
6426
+ ZEND_ASSERT (class_name && "must know class name when resolving parent type at compile time" );
6427
+ }
6428
+ }
6392
6429
zend_string_addref (class_name );
6393
6430
}
6394
6431
6395
6432
if (ast -> attr == ZEND_NAME_NOT_FQ
6396
- && zend_is_confusable_type (orig_name , & correct_name )
6397
- && zend_is_not_imported (orig_name )) {
6433
+ && zend_is_confusable_type (type_name , & correct_name )
6434
+ && zend_is_not_imported (type_name )) {
6398
6435
const char * extra =
6399
6436
FC (current_namespace ) ? " or import the class with \"use\"" : "" ;
6400
6437
if (correct_name ) {
6401
6438
zend_error (E_COMPILE_WARNING ,
6402
6439
"\"%s\" will be interpreted as a class name. Did you mean \"%s\"? "
6403
6440
"Write \"\\%s\"%s to suppress this warning" ,
6404
- ZSTR_VAL (orig_name ), correct_name , ZSTR_VAL (class_name ), extra );
6441
+ ZSTR_VAL (type_name ), correct_name , ZSTR_VAL (class_name ), extra );
6405
6442
} else {
6406
6443
zend_error (E_COMPILE_WARNING ,
6407
6444
"\"%s\" is not a supported builtin type "
6408
6445
"and will be interpreted as a class name. "
6409
6446
"Write \"\\%s\"%s to suppress this warning" ,
6410
- ZSTR_VAL (orig_name ), ZSTR_VAL (class_name ), extra );
6447
+ ZSTR_VAL (type_name ), ZSTR_VAL (class_name ), extra );
6411
6448
}
6412
6449
}
6413
6450
6414
6451
class_name = zend_new_interned_string (class_name );
6415
6452
zend_alloc_ce_cache (class_name );
6416
- return (zend_type ) ZEND_TYPE_INIT_CLASS (class_name , 0 , 0 );
6453
+ return (zend_type ) ZEND_TYPE_INIT_CLASS (class_name , /* allow null */ false, type_flags );
6417
6454
}
6418
6455
}
6419
6456
}
@@ -6495,7 +6532,34 @@ static void zend_is_type_list_redundant_by_single_type(zend_type_list *type_list
6495
6532
}
6496
6533
if (zend_string_equals_ci (ZEND_TYPE_NAME (type_list -> types [i ]), ZEND_TYPE_NAME (type ))) {
6497
6534
zend_string * single_type_str = zend_type_to_string (type );
6498
- zend_error_noreturn (E_COMPILE_ERROR , "Duplicate type %s is redundant" , ZSTR_VAL (single_type_str ));
6535
+ if (
6536
+ ZEND_TYPE_IS_RELATIVE_SELF (type )
6537
+ || ZEND_TYPE_IS_RELATIVE_PARENT (type )
6538
+ ) {
6539
+ if ( (
6540
+ ZEND_TYPE_FULL_MASK (type )
6541
+ & ZEND_TYPE_FULL_MASK (type_list -> types [i ])
6542
+ & (_ZEND_TYPE_SELF_BIT |_ZEND_TYPE_PARENT_BIT )) != 0
6543
+ ) {
6544
+ zend_error_noreturn (E_COMPILE_ERROR , "Duplicate type %s is redundant" , ZSTR_VAL (single_type_str ));
6545
+ }
6546
+ /* zend_type_to_string() will return "self" or "parent" where the resolved type is stored in
6547
+ * ZEND_TYPE_NAME() */
6548
+ zend_error_noreturn (E_COMPILE_ERROR , "%s resolves to %s which is redundant" ,
6549
+ ZSTR_VAL (single_type_str ), ZSTR_VAL (ZEND_TYPE_NAME (type ))
6550
+ );
6551
+ } else if (
6552
+ ZEND_TYPE_IS_RELATIVE_SELF (type_list -> types [i ])
6553
+ || ZEND_TYPE_IS_RELATIVE_PARENT (type_list -> types [i ])
6554
+ ) {
6555
+ /* zend_type_to_string() will return "self" or "parent" where the resolved type is stored in
6556
+ * ZEND_TYPE_NAME() */
6557
+ zend_error_noreturn (E_COMPILE_ERROR , "%s resolves to %s which is redundant" ,
6558
+ ZEND_TYPE_IS_RELATIVE_SELF (type_list -> types [i ]) ? "self" : "parent" , ZSTR_VAL (ZEND_TYPE_NAME (type ))
6559
+ );
6560
+ } else {
6561
+ zend_error_noreturn (E_COMPILE_ERROR , "Duplicate type %s is redundant" , ZSTR_VAL (single_type_str ));
6562
+ }
6499
6563
}
6500
6564
}
6501
6565
}
@@ -6534,6 +6598,7 @@ static zend_type zend_compile_typename(
6534
6598
/* Switch from single name to name list. */
6535
6599
type_list -> num_types = 1 ;
6536
6600
type_list -> types [0 ] = type ;
6601
+ /* Clear MAY_BE_* type flags */
6537
6602
ZEND_TYPE_FULL_MASK (type_list -> types [0 ]) &= ~_ZEND_TYPE_MAY_BE_MASK ;
6538
6603
}
6539
6604
/* Mark type as list type */
@@ -6580,20 +6645,26 @@ static zend_type zend_compile_typename(
6580
6645
"Type contains both true and false, bool should be used instead" );
6581
6646
}
6582
6647
ZEND_TYPE_FULL_MASK (type ) |= ZEND_TYPE_PURE_MASK (single_type );
6648
+ /* Clear MAY_BE_* type flags */
6583
6649
ZEND_TYPE_FULL_MASK (single_type ) &= ~_ZEND_TYPE_MAY_BE_MASK ;
6584
6650
6585
6651
if (ZEND_TYPE_IS_COMPLEX (single_type )) {
6586
6652
if (!ZEND_TYPE_IS_COMPLEX (type ) && !is_composite ) {
6587
6653
/* The first class type can be stored directly as the type ptr payload. */
6588
6654
ZEND_TYPE_SET_PTR (type , ZEND_TYPE_NAME (single_type ));
6589
6655
ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_NAME_BIT ;
6656
+ /* Add flags indicating the named type is self/parent */
6657
+ ZEND_TYPE_FULL_MASK (type ) |= (ZEND_TYPE_FULL_MASK (single_type ) & _ZEND_TYPE_RELATIVE_TYPE_MASK );
6590
6658
} else {
6591
6659
if (type_list -> num_types == 0 ) {
6592
6660
/* Switch from single name to name list. */
6593
6661
type_list -> num_types = 1 ;
6594
6662
type_list -> types [0 ] = type ;
6663
+ /* Clear MAY_BE_* type flags */
6595
6664
ZEND_TYPE_FULL_MASK (type_list -> types [0 ]) &= ~_ZEND_TYPE_MAY_BE_MASK ;
6596
6665
ZEND_TYPE_SET_LIST (type , type_list );
6666
+ /* Clear flags indicating the named type is self/parent */
6667
+ ZEND_TYPE_FULL_MASK (type ) &= ~_ZEND_TYPE_RELATIVE_TYPE_MASK ;
6597
6668
}
6598
6669
6599
6670
type_list -> types [type_list -> num_types ++ ] = single_type ;
@@ -6655,10 +6726,11 @@ static zend_type zend_compile_typename(
6655
6726
zend_string_release_ex (standard_type_str , false);
6656
6727
}
6657
6728
/* Check for "self" and "parent" too */
6658
- if (zend_string_equals_literal_ci (ZEND_TYPE_NAME (single_type ), "self" )
6659
- || zend_string_equals_literal_ci (ZEND_TYPE_NAME (single_type ), "parent" )) {
6660
- zend_error_noreturn (E_COMPILE_ERROR ,
6661
- "Type %s cannot be part of an intersection type" , ZSTR_VAL (ZEND_TYPE_NAME (single_type )));
6729
+ if (ZEND_TYPE_IS_RELATIVE_SELF (single_type )) {
6730
+ zend_error_noreturn (E_COMPILE_ERROR , "Type self cannot be part of an intersection type" );
6731
+ }
6732
+ if (ZEND_TYPE_IS_RELATIVE_PARENT (single_type )) {
6733
+ zend_error_noreturn (E_COMPILE_ERROR , "Type parent cannot be part of an intersection type" );
6662
6734
}
6663
6735
6664
6736
/* Add type to the type list */
0 commit comments