@@ -1946,6 +1946,31 @@ static zend_class_entry *fixup_trait_scope(const zend_function *fn, zend_class_e
1946
1946
return fn -> common .scope -> ce_flags & ZEND_ACC_TRAIT ? ce : fn -> common .scope ;
1947
1947
}
1948
1948
1949
+ /* If the type was resolved then either the zend_string pointer is different, or the zend_type_list is */
1950
+ static inline bool zend_was_type_resolved (zend_type original_type , zend_type resolved_type )
1951
+ {
1952
+ return original_type .ptr != resolved_type .ptr ;
1953
+ }
1954
+
1955
+ static zend_type zend_resolve_name_type (zend_type type , const zend_class_entry * const ce )
1956
+ {
1957
+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type ));
1958
+ if (ZEND_TYPE_IS_RELATIVE_SELF (type )) {
1959
+ 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 ));
1960
+ return resolved_type ;
1961
+ } else if (ZEND_TYPE_IS_RELATIVE_PARENT (type )) {
1962
+ if (!ce -> parent ) {
1963
+ zend_error_noreturn (E_COMPILE_ERROR ,
1964
+ "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1965
+ return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1966
+ }
1967
+ 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 ));
1968
+ return resolved_type ;
1969
+ } else {
1970
+ return type ;
1971
+ }
1972
+ }
1973
+
1949
1974
/* We cannot modify the type in-place (e.g. via a pointer) as it is written to SHM */
1950
1975
static zend_type zend_resolve_single_type (zend_type type , const zend_class_entry * const ce )
1951
1976
{
@@ -1956,62 +1981,49 @@ static zend_type zend_resolve_single_type(zend_type type, const zend_class_entry
1956
1981
1957
1982
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type ) || (ZEND_TYPE_HAS_LIST (type )));
1958
1983
if (ZEND_TYPE_HAS_NAME (type )) {
1959
- if (ZEND_TYPE_IS_RELATIVE_SELF (type )) {
1960
- 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 ));
1961
- return resolved_type ;
1962
- } else if (ZEND_TYPE_IS_RELATIVE_PARENT (type )) {
1963
- if (!ce -> parent ) {
1964
- zend_error_noreturn (E_COMPILE_ERROR ,
1965
- "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1966
- return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
1967
- }
1968
- 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 ));
1969
- return resolved_type ;
1970
- } else {
1971
- return type ;
1972
- }
1984
+ return zend_resolve_name_type (type , ce );
1973
1985
}
1974
1986
1975
1987
/* Intersection types cannot have relative class_types */
1976
1988
if (ZEND_TYPE_IS_INTERSECTION (type )) {
1977
1989
return type ;
1978
1990
}
1979
1991
1980
- const zend_type_list * union_type_list = ZEND_TYPE_LIST (type );
1981
- zend_type * single_type ;
1982
-
1983
- /* TODO Only do allocation if need to resolve types, as type is stored in SHM */
1984
- zend_type_list * new_union_type_list = zend_arena_alloc (& CG (arena ), ZEND_TYPE_LIST_SIZE (union_type_list -> num_types ));
1985
- memcpy (new_union_type_list , union_type_list , ZEND_TYPE_LIST_SIZE (union_type_list -> num_types ));
1992
+ zend_type_list * union_type_list = ZEND_TYPE_LIST (type );
1993
+ bool has_resolved_type = false;
1994
+ /* We don't use ZEND_TYPE_LIST_FOREACH() as we need to keep track of the array index */
1995
+ for (uint32_t i = 0 ; i < union_type_list -> num_types ; i ++ ) {
1996
+ zend_type single_type = union_type_list -> types [i ];
1986
1997
1987
- ZEND_TYPE_LIST_FOREACH (new_union_type_list , single_type ) {
1988
- ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* single_type ) || (ZEND_TYPE_IS_INTERSECTION (* single_type )));
1998
+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (single_type ) || (ZEND_TYPE_IS_INTERSECTION (single_type )));
1989
1999
1990
2000
/* Intersections types cannot have self or parent */
1991
- if (ZEND_TYPE_IS_INTERSECTION (* single_type )) {
2001
+ if (ZEND_TYPE_IS_INTERSECTION (single_type )) {
1992
2002
continue ;
1993
2003
}
1994
- if (ZEND_TYPE_IS_RELATIVE_SELF (* single_type )) {
1995
- 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 ));
1996
- memmove (single_type , & resolved_type , sizeof (zend_type ));
1997
- }
1998
- if (ZEND_TYPE_IS_RELATIVE_PARENT (* single_type )) {
1999
- if (!ce -> parent ) {
2000
- zend_error_noreturn (E_COMPILE_ERROR ,
2001
- "Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
2002
- return (zend_type ) ZEND_TYPE_INIT_NONE (0 );
2004
+
2005
+ zend_type resolved_type = zend_resolve_name_type (single_type , ce );
2006
+ if (zend_was_type_resolved (type , resolved_type )) {
2007
+ if (!has_resolved_type ) {
2008
+ const zend_type_list * old_union_type_list = ZEND_TYPE_LIST (type );
2009
+ union_type_list = zend_arena_alloc (& CG (arena ), ZEND_TYPE_LIST_SIZE (old_union_type_list -> num_types ));
2010
+ memcpy (union_type_list , old_union_type_list , ZEND_TYPE_LIST_SIZE (old_union_type_list -> num_types ));
2011
+ has_resolved_type = true;
2003
2012
}
2004
- 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 ));
2005
- memmove (single_type , & resolved_type , sizeof (zend_type ));
2013
+ union_type_list -> types [i ] = resolved_type ;
2006
2014
}
2007
- } ZEND_TYPE_LIST_FOREACH_END ();
2015
+ }
2008
2016
2009
- zend_type new_type = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
2010
- ZEND_TYPE_SET_LIST (new_type , new_union_type_list );
2011
- ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_ARENA_BIT ;
2012
- /* Inform that the type list is a union type */
2013
- ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_UNION_BIT ;
2014
- return new_type ;
2017
+ if (has_resolved_type ) {
2018
+ zend_type new_type = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
2019
+ ZEND_TYPE_SET_LIST (new_type , union_type_list );
2020
+ ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_ARENA_BIT ;
2021
+ /* Inform that the type list is a union type */
2022
+ ZEND_TYPE_FULL_MASK (new_type ) |= _ZEND_TYPE_UNION_BIT ;
2023
+ return new_type ;
2024
+ } else {
2025
+ return type ;
2026
+ }
2015
2027
}
2016
2028
2017
2029
static void zend_resolve_trait_relative_class_types (zend_function * const fn , const zend_class_entry * const ce )
@@ -2037,7 +2049,7 @@ static void zend_resolve_trait_relative_class_types(zend_function *const fn, con
2037
2049
for (uint32_t i = 0 ; i < num_args + has_return_type ; i ++ ) {
2038
2050
zend_type type = new_arg_infos [i ].type ;
2039
2051
zend_type resolved_type = zend_resolve_single_type (type , ce );
2040
- if (type . ptr != resolved_type . ptr ) {
2052
+ if (zend_was_type_resolved ( type , resolved_type ) ) {
2041
2053
if (!has_resolved_type ) {
2042
2054
new_arg_infos = zend_arena_alloc (& CG (arena ), allocated_size );
2043
2055
memcpy (new_arg_infos , fn -> common .arg_info - has_return_type , allocated_size );
0 commit comments