@@ -1519,6 +1519,30 @@ static reflection_type_kind get_type_kind(zend_type type) {
15191519 return NAMED_TYPE ;
15201520}
15211521
1522+ static zend_class_entry * reflection_resolve_declaring_class (zend_class_entry * ce )
1523+ {
1524+ return (ce && ce -> generic_parameters ) ? ce : NULL ;
1525+ }
1526+
1527+ static void reflection_resolve_fn_context (
1528+ zend_function * fptr ,
1529+ zend_class_entry * * declaring_class_out ,
1530+ zend_function * * declaring_fn_out )
1531+ {
1532+ * declaring_class_out = NULL ;
1533+ * declaring_fn_out = NULL ;
1534+ if (fptr -> type != ZEND_USER_FUNCTION ) {
1535+ return ;
1536+ }
1537+
1538+ const zend_op_array * op = & fptr -> op_array ;
1539+ if (op -> generic_parameters ) {
1540+ * declaring_fn_out = fptr ;
1541+ }
1542+
1543+ * declaring_class_out = reflection_resolve_declaring_class (op -> scope );
1544+ }
1545+
15221546/* {{{ reflection_type_factory_ex */
15231547static void reflection_type_factory_ex (
15241548 zend_type type , zval * object , bool legacy_behavior ,
@@ -2856,22 +2880,16 @@ ZEND_METHOD(ReflectionParameter, getType)
28562880 }
28572881
28582882 zend_type pre_erasure = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
2859- zend_class_entry * declaring_class = NULL ;
2860- zend_function * declaring_fn = NULL ;
2883+ zend_class_entry * declaring_class ;
2884+ zend_function * declaring_fn ;
2885+ reflection_resolve_fn_context (param -> fptr , & declaring_class , & declaring_fn );
28612886 if (param -> fptr -> type == ZEND_USER_FUNCTION ) {
28622887 zend_op_array * op = & param -> fptr -> op_array ;
28632888 if (op -> generic_types && op -> generic_types -> parameters ) {
28642889 zend_type * boxed = zend_hash_index_find_ptr (op -> generic_types -> parameters , param -> offset );
28652890 if (boxed ) {
28662891 pre_erasure = * boxed ;
2867- declaring_fn = param -> fptr ;
28682892 }
2869- } else if (op -> generic_parameters ) {
2870- declaring_fn = param -> fptr ;
2871- }
2872-
2873- if (op -> scope && op -> scope -> generic_parameters ) {
2874- declaring_class = op -> scope ;
28752893 }
28762894 }
28772895
@@ -3749,19 +3767,14 @@ ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
37493767 }
37503768
37513769 zend_type pre_erasure = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
3752- zend_class_entry * declaring_class = NULL ;
3753- zend_function * declaring_fn = NULL ;
3770+ zend_class_entry * declaring_class ;
3771+ zend_function * declaring_fn ;
3772+ reflection_resolve_fn_context (fptr , & declaring_class , & declaring_fn );
37543773 if (fptr -> type == ZEND_USER_FUNCTION ) {
37553774 zend_op_array * op = & fptr -> op_array ;
37563775 if (op -> generic_types && op -> generic_types -> return_type ) {
37573776 pre_erasure = * op -> generic_types -> return_type ;
37583777 }
3759- if (op -> generic_parameters ) {
3760- declaring_fn = fptr ;
3761- }
3762- if (op -> scope && op -> scope -> generic_parameters ) {
3763- declaring_class = op -> scope ;
3764- }
37653778 }
37663779
37673780 reflection_type_factory_ex (fptr -> common .arg_info [-1 ].type , return_value , true,
@@ -6516,7 +6529,6 @@ ZEND_METHOD(ReflectionProperty, getType)
65166529 }
65176530
65186531 zend_type pre_erasure = (zend_type ) ZEND_TYPE_INIT_NONE (0 );
6519- zend_class_entry * declaring_class = NULL ;
65206532 zend_class_entry * ce = ref -> prop -> ce ;
65216533 if (ce && ce -> generic_types && ce -> generic_types -> properties ) {
65226534 zend_type * boxed = zend_hash_find_ptr (ce -> generic_types -> properties , ref -> prop -> name );
@@ -6525,12 +6537,8 @@ ZEND_METHOD(ReflectionProperty, getType)
65256537 }
65266538 }
65276539
6528- if (ce && ce -> generic_parameters ) {
6529- declaring_class = ce ;
6530- }
6531-
65326540 reflection_type_factory_ex (ref -> prop -> type , return_value , true,
6533- pre_erasure , declaring_class , NULL );
6541+ pre_erasure , reflection_resolve_declaring_class ( ce ) , NULL );
65346542}
65356543/* }}} */
65366544
@@ -8721,6 +8729,24 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentClass)
87218729 RETURN_EMPTY_ARRAY ();
87228730}
87238731
8732+ static bool reflection_try_build_named_args_from_table (HashTable * ht , zend_class_entry * ce , zend_string * name , zval * return_value )
8733+ {
8734+ if (!ht ) {
8735+ return false;
8736+ }
8737+
8738+ zval * zv ;
8739+ ZEND_HASH_FOREACH_VAL (ht , zv ) {
8740+ zend_type * boxed = (zend_type * ) Z_PTR_P (zv );
8741+ zend_type_named_with_args * named = ZEND_TYPE_NAMED_WITH_ARGS (* boxed );
8742+ if (zend_string_equals_ci (named -> name , name )) {
8743+ reflection_build_named_args_list (return_value , boxed , ce );
8744+ return true;
8745+ }
8746+ } ZEND_HASH_FOREACH_END ();
8747+ return false;
8748+ }
8749+
87248750ZEND_METHOD (ReflectionClass , getGenericArgumentsForParentInterface )
87258751{
87268752 reflection_object * intern ;
@@ -8732,6 +8758,11 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentInterface)
87328758 ZEND_PARSE_PARAMETERS_END ();
87338759 GET_REFLECTION_OBJECT_PTR (ce );
87348760
8761+ HashTable * ht = ce -> generic_types ? ce -> generic_types -> implements : NULL ;
8762+ if (reflection_try_build_named_args_from_table (ht , ce , name , return_value )) {
8763+ return ;
8764+ }
8765+
87358766 bool is_ancestor = false;
87368767 if (ce -> ce_flags & ZEND_ACC_LINKED ) {
87378768 for (uint32_t i = 0 ; i < ce -> num_interfaces ; i ++ ) {
@@ -8753,18 +8784,6 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForParentInterface)
87538784 "%s is not an ancestor interface of %s" , ZSTR_VAL (name ), ZSTR_VAL (ce -> name ));
87548785 RETURN_THROWS ();
87558786 }
8756-
8757- if (ce -> generic_types && ce -> generic_types -> implements ) {
8758- zval * zv ;
8759- ZEND_HASH_FOREACH_VAL (ce -> generic_types -> implements , zv ) {
8760- zend_type * boxed = (zend_type * ) Z_PTR_P (zv );
8761- zend_type_named_with_args * named = ZEND_TYPE_NAMED_WITH_ARGS (* boxed );
8762- if (zend_string_equals_ci (named -> name , name )) {
8763- reflection_build_named_args_list (return_value , boxed , ce );
8764- return ;
8765- }
8766- } ZEND_HASH_FOREACH_END ();
8767- }
87688787 RETURN_EMPTY_ARRAY ();
87698788}
87708789
@@ -8779,6 +8798,11 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForUsedTrait)
87798798 ZEND_PARSE_PARAMETERS_END ();
87808799 GET_REFLECTION_OBJECT_PTR (ce );
87818800
8801+ HashTable * ht = ce -> generic_types ? ce -> generic_types -> trait_uses : NULL ;
8802+ if (reflection_try_build_named_args_from_table (ht , ce , name , return_value )) {
8803+ return ;
8804+ }
8805+
87828806 bool is_used = false;
87838807 for (uint32_t i = 0 ; i < ce -> num_traits ; i ++ ) {
87848808 if (zend_string_equals_ci (ce -> trait_names [i ].name , name )) {
@@ -8791,18 +8815,6 @@ ZEND_METHOD(ReflectionClass, getGenericArgumentsForUsedTrait)
87918815 "%s is not a trait used by %s" , ZSTR_VAL (name ), ZSTR_VAL (ce -> name ));
87928816 RETURN_THROWS ();
87938817 }
8794-
8795- if (ce -> generic_types && ce -> generic_types -> trait_uses ) {
8796- zval * zv ;
8797- ZEND_HASH_FOREACH_VAL (ce -> generic_types -> trait_uses , zv ) {
8798- zend_type * boxed = (zend_type * ) Z_PTR_P (zv );
8799- zend_type_named_with_args * named = ZEND_TYPE_NAMED_WITH_ARGS (* boxed );
8800- if (zend_string_equals_ci (named -> name , name )) {
8801- reflection_build_named_args_list (return_value , boxed , ce );
8802- return ;
8803- }
8804- } ZEND_HASH_FOREACH_END ();
8805- }
88068818 RETURN_EMPTY_ARRAY ();
88078819}
88088820
0 commit comments