@@ -1898,6 +1898,31 @@ static zend_class_entry *fixup_trait_scope(const zend_function *fn, zend_class_e
1898
1898
return fn -> common .scope -> ce_flags & ZEND_ACC_TRAIT ? ce : fn -> common .scope ;
1899
1899
}
1900
1900
1901
+ /* If the type was resolved then either the zend_string pointer is different, or the zend_type_list is */
1902
+ static inline bool zend_was_type_resolved (zend_type original_type , zend_type resolved_type )
1903
+ {
1904
+ return original_type .ptr != resolved_type .ptr ;
1905
+ }
1906
+
1907
+ static zend_type zend_resolve_name_type (zend_type type , const zend_class_entry * const ce )
1908
+ {
1909
+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type ));
1910
+ if (ZEND_TYPE_IS_RELATIVE_SELF (type )) {
1911
+ zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (type ));
1912
+ return resolved_type ;
1913
+ } else if (ZEND_TYPE_IS_RELATIVE_PARENT (type )) {
1914
+ if (!ce -> parent ) {
1915
+ zend_error_noreturn (E_COMPILE_ERROR ,
1916
+ "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1917
+ return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1918
+ }
1919
+ zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> parent -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (type ));
1920
+ return resolved_type ;
1921
+ } else {
1922
+ return type ;
1923
+ }
1924
+ }
1925
+
1901
1926
/* We cannot modify the type in-place (e.g. via a pointer) as it is written to SHM */
1902
1927
static zend_type zend_resolve_single_type (zend_type type , const zend_class_entry * const ce )
1903
1928
{
@@ -1908,62 +1933,49 @@ static zend_type zend_resolve_single_type(zend_type type, const zend_class_entry
1908
1933
1909
1934
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type ) || (ZEND_TYPE_HAS_LIST (type )));
1910
1935
if (ZEND_TYPE_HAS_NAME (type )) {
1911
- if (ZEND_TYPE_IS_RELATIVE_SELF (type )) {
1912
- zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (type ));
1913
- return resolved_type ;
1914
- } else if (ZEND_TYPE_IS_RELATIVE_PARENT (type )) {
1915
- if (!ce -> parent ) {
1916
- zend_error_noreturn (E_COMPILE_ERROR ,
1917
- "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1918
- return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1919
- }
1920
- zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> parent -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (type ));
1921
- return resolved_type ;
1922
- } else {
1923
- return type ;
1924
- }
1936
+ return zend_resolve_name_type (type , ce );
1925
1937
}
1926
1938
1927
1939
/* Intersection types cannot have relative class_types */
1928
1940
if (ZEND_TYPE_IS_INTERSECTION (type )) {
1929
1941
return type ;
1930
1942
}
1931
1943
1932
- const zend_type_list * union_type_list = ZEND_TYPE_LIST (type );
1933
- zend_type * single_type ;
1934
-
1935
- /* TODO Only do allocation if need to resolve types, as type is stored in SHM */
1936
- zend_type_list * new_union_type_list = zend_arena_alloc (& CG (arena ), ZEND_TYPE_LIST_SIZE (union_type_list -> num_types ));
1937
- memcpy (new_union_type_list , union_type_list , ZEND_TYPE_LIST_SIZE (union_type_list -> num_types ));
1944
+ zend_type_list * union_type_list = ZEND_TYPE_LIST (type );
1945
+ bool has_resolved_type = false;
1946
+ /* We don't use ZEND_TYPE_LIST_FOREACH() as we need to keep track of the array index */
1947
+ for (uint32_t i = 0 ; i < union_type_list -> num_types ; i ++ ) {
1948
+ zend_type single_type = union_type_list -> types [i ];
1938
1949
1939
- ZEND_TYPE_LIST_FOREACH (new_union_type_list , single_type ) {
1940
- ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* single_type ) || (ZEND_TYPE_IS_INTERSECTION (* single_type )));
1950
+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (single_type ) || (ZEND_TYPE_IS_INTERSECTION (single_type )));
1941
1951
1942
1952
/* Intersections types cannot have self or parent */
1943
- if (ZEND_TYPE_IS_INTERSECTION (* single_type )) {
1953
+ if (ZEND_TYPE_IS_INTERSECTION (single_type )) {
1944
1954
continue ;
1945
1955
}
1946
- if (ZEND_TYPE_IS_RELATIVE_SELF (* single_type )) {
1947
- zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (* single_type ));
1948
- memmove (single_type , & resolved_type , sizeof (zend_type ));
1949
- }
1950
- if (ZEND_TYPE_IS_RELATIVE_PARENT (* single_type )) {
1951
- if (!ce -> parent ) {
1952
- zend_error_noreturn (E_COMPILE_ERROR ,
1953
- "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1954
- return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1956
+
1957
+ zend_type resolved_type = zend_resolve_name_type (single_type , ce );
1958
+ if (zend_was_type_resolved (type , resolved_type )) {
1959
+ if (!has_resolved_type ) {
1960
+ const zend_type_list * old_union_type_list = ZEND_TYPE_LIST (type );
1961
+ union_type_list = zend_arena_alloc (& CG (arena ), ZEND_TYPE_LIST_SIZE (old_union_type_list -> num_types ));
1962
+ memcpy (union_type_list , old_union_type_list , ZEND_TYPE_LIST_SIZE (old_union_type_list -> num_types ));
1963
+ has_resolved_type = true;
1955
1964
}
1956
- zend_type resolved_type = (zend_type ) ZEND_TYPE_INIT_CLASS (zend_string_copy (ce -> parent -> name ), /* allows_null */ false, /* extra_flags */ ZEND_TYPE_FULL_MASK (* single_type ));
1957
- memmove (single_type , & resolved_type , sizeof (zend_type ));
1965
+ union_type_list -> types [i ] = resolved_type ;
1958
1966
}
1959
- } ZEND_TYPE_LIST_FOREACH_END ();
1967
+ }
1960
1968
1961
- zend_type new_type = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1962
- ZEND_TYPE_SET_LIST (new_type , new_union_type_list );
1963
- ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_ARENA_BIT ;
1964
- /* Inform that the type list is a union type */
1965
- ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_UNION_BIT ;
1966
- return new_type ;
1969
+ if (has_resolved_type ) {
1970
+ zend_type new_type = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1971
+ ZEND_TYPE_SET_LIST (new_type , union_type_list );
1972
+ ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_ARENA_BIT ;
1973
+ /* Inform that the type list is a union type */
1974
+ ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_UNION_BIT ;
1975
+ return new_type ;
1976
+ } else {
1977
+ return type ;
1978
+ }
1967
1979
}
1968
1980
1969
1981
static void zend_resolve_trait_relative_class_types (zend_function * const fn , const zend_class_entry * const ce )
@@ -1989,7 +2001,7 @@ static void zend_resolve_trait_relative_class_types(zend_function *const fn, con
1989
2001
for (uint32_t i = 0 ; i < num_args + has_return_type ; i ++ ) {
1990
2002
zend_type type = new_arg_infos [i ].type ;
1991
2003
zend_type resolved_type = zend_resolve_single_type (type , ce );
1992
- if (type . ptr != resolved_type . ptr ) {
2004
+ if (zend_was_type_resolved ( type , resolved_type ) ) {
1993
2005
if (!has_resolved_type ) {
1994
2006
new_arg_infos = zend_arena_alloc (& CG (arena ), allocated_size );
1995
2007
memcpy (new_arg_infos , fn -> common .arg_info - has_return_type , allocated_size );
0 commit comments