@@ -1898,18 +1898,45 @@ 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
- static void zend_resolve_trait_relative_class_types (zend_type * type , /* const */ zend_class_entry * ce )
1901
+ /* We cannot modify the type in-place (e.g. via a pointer) as it is written to SHM */
1902
+ static zend_type zend_resolve_single_type (zend_type type , const zend_class_entry * const ce )
1902
1903
{
1903
- /* Only built-in types */
1904
- if (!ZEND_TYPE_IS_COMPLEX (* type )) {
1905
- return ;
1904
+ /* Only built-in types + static */
1905
+ if (!ZEND_TYPE_IS_COMPLEX (type )) {
1906
+ return type ;
1906
1907
}
1907
- /* We are adding trait methods to another trait, delay resolution */
1908
- if (ce -> ce_flags & ZEND_ACC_TRAIT ) {
1909
- return ;
1908
+
1909
+ ZEND_ASSERT (ZEND_TYPE_HAS_NAME (type ) || (ZEND_TYPE_HAS_LIST (type )));
1910
+ 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
+ }
1925
+ }
1926
+
1927
+ /* Intersection types cannot have relative class_types */
1928
+ if (ZEND_TYPE_IS_INTERSECTION (type )) {
1929
+ return type ;
1910
1930
}
1931
+
1932
+ const zend_type_list * union_type_list = ZEND_TYPE_LIST (type );
1911
1933
zend_type * single_type ;
1912
- ZEND_TYPE_FOREACH (* 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 ));
1938
+
1939
+ ZEND_TYPE_LIST_FOREACH (new_union_type_list , single_type ) {
1913
1940
ZEND_ASSERT (ZEND_TYPE_HAS_NAME (* single_type ) || (ZEND_TYPE_IS_INTERSECTION (* single_type )));
1914
1941
1915
1942
/* Intersections types cannot have self or parent */
@@ -1918,20 +1945,52 @@ static void zend_resolve_trait_relative_class_types(zend_type *type, /* const */
1918
1945
}
1919
1946
if (ZEND_TYPE_IS_RELATIVE_SELF (* single_type )) {
1920
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 ));
1921
- /* Cannot use memcpy as we violate the restrict constraint of src and dest */
1922
1948
memmove (single_type , & resolved_type , sizeof (zend_type ));
1923
1949
}
1924
1950
if (ZEND_TYPE_IS_RELATIVE_PARENT (* single_type )) {
1925
1951
if (!ce -> parent ) {
1926
1952
zend_error_noreturn (E_COMPILE_ERROR ,
1927
1953
"Cannot use trait which has \"parent\" as a type when current class scope has no parent" );
1928
- return ;
1954
+ return ( zend_type ) ZEND_TYPE_INIT_NONE ( 0 ) ;
1929
1955
}
1930
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 ));
1931
- /* Cannot use memcpy as we violate the restrict constraint of src and dest */
1932
1957
memmove (single_type , & resolved_type , sizeof (zend_type ));
1933
1958
}
1934
- } ZEND_TYPE_FOREACH_END ();
1959
+ } ZEND_TYPE_LIST_FOREACH_END ();
1960
+
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 ;
1967
+ }
1968
+
1969
+ static void zend_resolve_trait_relative_class_types (zend_function * const fn , const zend_class_entry * const ce )
1970
+ {
1971
+ /* We are adding trait methods to another trait, delay resolution */
1972
+ if (ce -> ce_flags & ZEND_ACC_TRAIT ) {
1973
+ return ;
1974
+ }
1975
+ /* No type info */
1976
+ if (!fn -> common .arg_info ) {
1977
+ return ;
1978
+ }
1979
+
1980
+ bool has_return_type = fn -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ;
1981
+ uint32_t num_args = fn -> common .num_args ;
1982
+ /* TODO Only do allocation if need to resolve types, as arg_info is stored in SHM */
1983
+ size_t allocated_size = sizeof (zend_arg_info ) * (has_return_type + num_args );
1984
+
1985
+ zend_arg_info * new_arg_infos = zend_arena_alloc (& CG (arena ), allocated_size );
1986
+ memcpy (new_arg_infos , fn -> common .arg_info - has_return_type , allocated_size );
1987
+ fn -> common .arg_info = new_arg_infos + has_return_type ;
1988
+
1989
+ for (uint32_t i = 0 ; i < num_args + has_return_type ; i ++ ) {
1990
+ // TODO Handle variadic parameter types?
1991
+ zend_type type = new_arg_infos [i ].type ;
1992
+ new_arg_infos [i ].type = zend_resolve_single_type (type , ce );
1993
+ }
1935
1994
}
1936
1995
1937
1996
static void zend_add_trait_method (zend_class_entry * ce , zend_string * name , zend_string * key , zend_function * fn ) /* {{{ */
@@ -1983,34 +2042,12 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
1983
2042
if (UNEXPECTED (fn -> type == ZEND_INTERNAL_FUNCTION )) {
1984
2043
new_fn = zend_arena_alloc (& CG (arena ), sizeof (zend_internal_function ));
1985
2044
memcpy (new_fn , fn , sizeof (zend_internal_function ));
1986
- if (new_fn -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) {
1987
- zend_type * return_type = & new_fn -> common .arg_info [-1 ].type ;
1988
- zend_resolve_trait_relative_class_types (return_type , ce );
1989
- }
1990
-
1991
- uint32_t num_args = new_fn -> common .num_args ;
1992
- for (uint32_t i = 0 ; i < num_args ; i ++ ) {
1993
- // TODO Handle variadic parameter types?
1994
- zend_arg_info * arg_info = & new_fn -> common .arg_info [i ];
1995
- zend_type * type = & arg_info -> type ;
1996
- zend_resolve_trait_relative_class_types (type , ce );
1997
- }
2045
+ zend_resolve_trait_relative_class_types (new_fn , ce );
1998
2046
new_fn -> common .fn_flags |= ZEND_ACC_ARENA_ALLOCATED ;
1999
2047
} else {
2000
2048
new_fn = zend_arena_alloc (& CG (arena ), sizeof (zend_op_array ));
2001
2049
memcpy (new_fn , fn , sizeof (zend_op_array ));
2002
- if (new_fn -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) {
2003
- zend_type * return_type = & new_fn -> common .arg_info [-1 ].type ;
2004
- zend_resolve_trait_relative_class_types (return_type , ce );
2005
- }
2006
-
2007
- uint32_t num_args = new_fn -> common .num_args ;
2008
- for (uint32_t i = 0 ; i < num_args ; i ++ ) {
2009
- // TODO Handle variadic parameter types?
2010
- zend_arg_info * arg_info = & new_fn -> common .arg_info [i ];
2011
- zend_type * type = & arg_info -> type ;
2012
- zend_resolve_trait_relative_class_types (type , ce );
2013
- }
2050
+ zend_resolve_trait_relative_class_types (new_fn , ce );
2014
2051
new_fn -> op_array .fn_flags |= ZEND_ACC_TRAIT_CLONE ;
2015
2052
new_fn -> op_array .fn_flags &= ~ZEND_ACC_IMMUTABLE ;
2016
2053
}
0 commit comments