Skip to content

Commit d5a51e6

Browse files
committed
Do not preserve BC for self/parent and always resolve when possible
1 parent 8635eea commit d5a51e6

File tree

41 files changed

+394
-779
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+394
-779
lines changed

Zend/tests/type_declarations/intersection_types/invalid_types/invalid_parent_type.phpt renamed to Zend/tests/type_declarations/intersection_types/invalid_types/invalid_unresolved_relative_type_parent.phpt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
--TEST--
2-
parent type cannot take part in an intersection type
2+
parent type cannot take part in an intersection type when unresolved
33
--FILE--
44
<?php
55

6-
class A {}
7-
8-
class B extends A {
6+
trait T {
97
public function foo(): parent&Iterator {}
108
}
119

Zend/tests/type_declarations/intersection_types/invalid_types/invalid_self_type.phpt renamed to Zend/tests/type_declarations/intersection_types/invalid_types/invalid_unresolved_relative_type_self.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
--TEST--
2-
self type cannot take part in an intersection type
2+
self type cannot take part in an intersection type when unresolved
33
--FILE--
44
<?php
55

6-
class A {
6+
trait T {
77
public function foo(): self&Iterator {}
88
}
99

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
parent type cannot take part in an intersection type
3+
--FILE--
4+
<?php
5+
6+
class A {}
7+
8+
class B extends A {
9+
public function foo(): parent&Iterator {}
10+
}
11+
12+
class C extends A {
13+
public function foo(): self&Iterator {}
14+
}
15+
16+
?>
17+
==DONE==
18+
--EXPECT--
19+
==DONE==

Zend/tests/type_declarations/union_types/redundant_types/duplicate_relative_class_parent_type.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ class Bar extends Foo {
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: Duplicate type parent is redundant in %s on line %d
15+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/duplicate_relative_class_self_type.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class Foo {
99

1010
?>
1111
--EXPECTF--
12-
Fatal error: Duplicate type self is redundant in %s on line %d
12+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/duplicate_resolved_relative_class_type_variation1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class Foo {
99

1010
?>
1111
--EXPECTF--
12-
Fatal error: self resolves to Foo which is redundant in %s on line %d
12+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/duplicate_resolved_relative_class_type_variation2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class Foo {
99

1010
?>
1111
--EXPECTF--
12-
Fatal error: self resolves to Foo which is redundant in %s on line %d
12+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/duplicate_resolved_relative_class_type_variation3.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ class Bar extends Foo {
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: parent resolves to Foo which is redundant in %s on line %d
15+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/tests/type_declarations/union_types/redundant_types/duplicate_resolved_relative_class_type_variation4.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ class Bar extends Foo {
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: parent resolves to Foo which is redundant in %s on line %d
15+
Fatal error: Duplicate type Foo is redundant in %s on line %d

Zend/zend_compile.c

Lines changed: 11 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,8 +1354,6 @@ static zend_string *add_intersection_type(zend_string *str,
13541354
ZEND_TYPE_LIST_FOREACH(intersection_type_list, single_type) {
13551355
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type));
13561356
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*single_type));
1357-
ZEND_ASSERT(!ZEND_TYPE_IS_RELATIVE_SELF(*single_type) && "Compile time disallowed to have 'self' in intersection");
1358-
ZEND_ASSERT(!ZEND_TYPE_IS_RELATIVE_PARENT(*single_type) && "Compile time disallowed to have 'parent' in intersection");
13591357

13601358
intersection_str = add_type_string(intersection_str, ZEND_TYPE_NAME(*single_type), /* is_intersection */ true);
13611359
} ZEND_TYPE_LIST_FOREACH_END();
@@ -1390,29 +1388,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
13901388
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
13911389
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type));
13921390

1393-
/* We already have resolved types from compile time
1394-
* Mimic unresolved types for BC with "self" and "parent" */
1395-
if (!scope && ZEND_TYPE_IS_RELATIVE_SELF(*list_type)) {
1396-
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_SELF), /* is_intersection */ false);
1397-
} else if (!scope && ZEND_TYPE_IS_RELATIVE_PARENT(*list_type)) {
1398-
str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_PARENT), /* is_intersection */ false);
1399-
} else {
1400-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1401-
zend_string *resolved = resolve_class_name(name, scope);
1402-
str = add_type_string(str, resolved, /* is_intersection */ false);
1403-
zend_string_release(resolved);
1404-
}
1391+
zend_string *name = ZEND_TYPE_NAME(*list_type);
1392+
zend_string *resolved = resolve_class_name(name, scope);
1393+
str = add_type_string(str, resolved, /* is_intersection */ false);
1394+
zend_string_release(resolved);
14051395
} ZEND_TYPE_LIST_FOREACH_END();
14061396
} else if (ZEND_TYPE_HAS_NAME(type)) {
1407-
/* We already have resolved types from compile time
1408-
* Mimic unresolved types for BC with "self" and "parent" */
1409-
if (!scope && ZEND_TYPE_IS_RELATIVE_SELF(type)) {
1410-
str = ZSTR_KNOWN(ZEND_STR_SELF);
1411-
} else if (!scope && ZEND_TYPE_IS_RELATIVE_PARENT(type)) {
1412-
str = ZSTR_KNOWN(ZEND_STR_PARENT);
1413-
} else {
1414-
str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
1415-
}
1397+
str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
14161398
}
14171399

14181400
uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
@@ -6631,7 +6613,6 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
66316613
} else {
66326614
const char *correct_name;
66336615
uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
6634-
uint32_t type_flags = 0;
66356616
zend_string *class_name = type_name;
66366617

66376618
if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
@@ -6642,15 +6623,13 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
66426623

66436624
zend_ensure_valid_class_fetch_type(fetch_type);
66446625
if (fetch_type == ZEND_FETCH_CLASS_SELF) {
6645-
type_flags = _ZEND_TYPE_SELF_BIT;
66466626
/* Scope might be unknown for unbound closures and traits */
66476627
if (zend_is_scope_known()) {
66486628
class_name = CG(active_class_entry)->name;
66496629
ZEND_ASSERT(class_name && "must know class name when resolving self type at compile time");
66506630
}
66516631
} else {
66526632
ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_PARENT);
6653-
type_flags = _ZEND_TYPE_PARENT_BIT;
66546633
/* Scope might be unknown for unbound closures and traits */
66556634
if (zend_is_scope_known()) {
66566635
class_name = CG(active_class_entry)->parent_name;
@@ -6681,7 +6660,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
66816660

66826661
class_name = zend_new_interned_string(class_name);
66836662
zend_alloc_ce_cache(class_name);
6684-
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, /* allow null */ false, type_flags);
6663+
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, /* allow null */ false, 0);
66856664
}
66866665
}
66876666
}
@@ -6763,28 +6742,7 @@ static void zend_is_type_list_redundant_by_single_type(zend_type_list *type_list
67636742
}
67646743
if (zend_string_equals_ci(ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(type))) {
67656744
zend_string *single_type_str = zend_type_to_string(type);
6766-
if (ZEND_TYPE_IS_RELATIVE_TYPE(type)) {
6767-
if ( (
6768-
ZEND_TYPE_FULL_MASK(type)
6769-
& ZEND_TYPE_FULL_MASK(type_list->types[i])
6770-
& (_ZEND_TYPE_RELATIVE_TYPE_MASK)) != 0
6771-
) {
6772-
zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
6773-
}
6774-
/* zend_type_to_string() will return "self" or "parent" where the resolved type is stored in
6775-
* ZEND_TYPE_NAME() */
6776-
zend_error_noreturn(E_COMPILE_ERROR, "%s resolves to %s which is redundant",
6777-
ZSTR_VAL(single_type_str), ZSTR_VAL(ZEND_TYPE_NAME(type))
6778-
);
6779-
} else if (ZEND_TYPE_IS_RELATIVE_TYPE(type_list->types[i])) {
6780-
/* zend_type_to_string() will return "self" or "parent" where the resolved type is stored in
6781-
* ZEND_TYPE_NAME() */
6782-
zend_error_noreturn(E_COMPILE_ERROR, "%s resolves to %s which is redundant",
6783-
ZEND_TYPE_IS_RELATIVE_SELF(type_list->types[i]) ? "self" : "parent", ZSTR_VAL(ZEND_TYPE_NAME(type))
6784-
);
6785-
} else {
6786-
zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
6787-
}
6745+
zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
67886746
}
67896747
}
67906748
}
@@ -6880,8 +6838,6 @@ static zend_type zend_compile_typename_ex(
68806838
/* The first class type can be stored directly as the type ptr payload. */
68816839
ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
68826840
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
6883-
/* Add flags indicating the named type is self/parent */
6884-
ZEND_TYPE_FULL_MASK(type) |= (ZEND_TYPE_FULL_MASK(single_type) & _ZEND_TYPE_RELATIVE_TYPE_MASK);
68856841
} else {
68866842
if (type_list->num_types == 0) {
68876843
/* Switch from single name to name list. */
@@ -6890,8 +6846,6 @@ static zend_type zend_compile_typename_ex(
68906846
/* Clear MAY_BE_* type flags */
68916847
ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
68926848
ZEND_TYPE_SET_LIST(type, type_list);
6893-
/* Clear flags indicating the named type is self/parent */
6894-
ZEND_TYPE_FULL_MASK(type) &= ~_ZEND_TYPE_RELATIVE_TYPE_MASK;
68956849
}
68966850

68976851
type_list->types[type_list->num_types++] = single_type;
@@ -6953,11 +6907,10 @@ static zend_type zend_compile_typename_ex(
69536907
zend_string_release_ex(standard_type_str, false);
69546908
}
69556909
/* Check for "self" and "parent" too */
6956-
if (ZEND_TYPE_IS_RELATIVE_SELF(single_type)) {
6957-
zend_error_noreturn(E_COMPILE_ERROR, "Type self cannot be part of an intersection type");
6958-
}
6959-
if (ZEND_TYPE_IS_RELATIVE_PARENT(single_type)) {
6960-
zend_error_noreturn(E_COMPILE_ERROR, "Type parent cannot be part of an intersection type");
6910+
if (zend_string_equals_literal_ci(ZEND_TYPE_NAME(single_type), "self")
6911+
|| zend_string_equals_literal_ci(ZEND_TYPE_NAME(single_type), "parent")) {
6912+
zend_error_noreturn(E_COMPILE_ERROR,
6913+
"Type %s cannot be part of an intersection type", ZSTR_VAL(ZEND_TYPE_NAME(single_type)));
69616914
}
69626915

69636916
/* Add type to the type list */

Zend/zend_inheritance.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,10 +1955,10 @@ static inline bool zend_was_type_resolved(zend_type original_type, zend_type res
19551955
static zend_type zend_resolve_name_type(zend_type type, const zend_class_entry *const ce)
19561956
{
19571957
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(type));
1958-
if (ZEND_TYPE_IS_RELATIVE_SELF(type)) {
1958+
if (zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "self")) {
19591959
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));
19601960
return resolved_type;
1961-
} else if (ZEND_TYPE_IS_RELATIVE_PARENT(type)) {
1961+
} else if (zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "parent")) {
19621962
if (!ce->parent) {
19631963
zend_error_noreturn(E_COMPILE_ERROR,
19641964
"Cannot use trait which has \"parent\" as a type when current class scope has no parent");

Zend/zend_types.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,8 @@ typedef struct {
142142
zend_type types[1];
143143
} zend_type_list;
144144

145-
#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 27
146-
#define _ZEND_TYPE_MASK ((1u << 27) - 1)
147-
/* Only one of these bits may be set. */
148-
#define _ZEND_TYPE_PARENT_BIT (1u << 26)
149-
#define _ZEND_TYPE_SELF_BIT (1u << 25)
150-
#define _ZEND_TYPE_RELATIVE_TYPE_MASK (_ZEND_TYPE_SELF_BIT|_ZEND_TYPE_PARENT_BIT)
145+
#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 25
146+
#define _ZEND_TYPE_MASK ((1u << 25) - 1)
151147
/* Only one of these bits may be set. */
152148
#define _ZEND_TYPE_NAME_BIT (1u << 24)
153149
// Used to signify that type.ptr is not a `zend_string*` but a `const char*`,
@@ -170,17 +166,6 @@ typedef struct {
170166
#define ZEND_TYPE_IS_SET(t) \
171167
(((t).type_mask & _ZEND_TYPE_MASK) != 0)
172168

173-
174-
/* To determine if the type resolved type was written with "self" or "parent" */
175-
#define ZEND_TYPE_IS_RELATIVE_TYPE(t) \
176-
((((t).type_mask) & _ZEND_TYPE_RELATIVE_TYPE_MASK) != 0)
177-
/* To determine if the type resolved type was written with "self" */
178-
#define ZEND_TYPE_IS_RELATIVE_SELF(t) \
179-
((((t).type_mask) & _ZEND_TYPE_SELF_BIT) != 0)
180-
/* To determine if the type resolved type was written with "parent" */
181-
#define ZEND_TYPE_IS_RELATIVE_PARENT(t) \
182-
((((t).type_mask) & _ZEND_TYPE_PARENT_BIT) != 0)
183-
184169
/* If a type is complex it means it's either a list with a union or intersection,
185170
* or the void pointer is a class name */
186171
#define ZEND_TYPE_IS_COMPLEX(t) \

ext/reflection/php_reflection.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,10 @@ static reflection_type_kind get_type_kind(zend_type type) {
13681368
}
13691369

13701370
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(type));
1371-
if (ZEND_TYPE_IS_RELATIVE_TYPE(type)) {
1371+
if (
1372+
zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "self")
1373+
|| zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "parent")
1374+
) {
13721375
return RELATIVE_TYPE;
13731376
}
13741377
return NAMED_TYPE;
@@ -2688,14 +2691,15 @@ ZEND_METHOD(ReflectionParameter, getClass)
26882691
* TODO: Think about moving these checks to the compiler or some sort of
26892692
* lint-mode.
26902693
*/
2691-
if (ZEND_TYPE_IS_RELATIVE_SELF(param->arg_info->type)) {
2694+
zend_string *class_name = ZEND_TYPE_NAME(param->arg_info->type);
2695+
if (zend_string_equals_literal_ci(class_name, "self")) {
26922696
ce = param->fptr->common.scope;
26932697
if (!ce) {
26942698
zend_throw_exception_ex(reflection_exception_ptr, 0,
26952699
"Parameter uses \"self\" as type but function is not a class member");
26962700
RETURN_THROWS();
26972701
}
2698-
} else if (ZEND_TYPE_IS_RELATIVE_PARENT(param->arg_info->type)) {
2702+
} else if (zend_string_equals_literal_ci(class_name, "parent")) {
26992703
ce = param->fptr->common.scope;
27002704
if (!ce) {
27012705
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -2709,7 +2713,6 @@ ZEND_METHOD(ReflectionParameter, getClass)
27092713
}
27102714
ce = ce->parent;
27112715
} else {
2712-
zend_string *class_name = ZEND_TYPE_NAME(param->arg_info->type);
27132716
ce = zend_lookup_class(class_name);
27142717
if (!ce) {
27152718
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -3157,11 +3160,11 @@ ZEND_METHOD(ReflectionRelativeClassType, resolveToNamedType)
31573160
"Cannot resolve \"static\" type of an interface");
31583161
RETURN_THROWS();
31593162
}
3160-
resolved_type = (zend_type) ZEND_TYPE_INIT_CLASS(intern->ce->name, allows_null, /*extra flags */ 0);
3163+
resolved_type = (zend_type) ZEND_TYPE_INIT_CLASS(intern->ce->name, allows_null, /* extra flags */ 0);
31613164
} else {
3162-
ZEND_ASSERT(ZEND_TYPE_IS_RELATIVE_TYPE(param->type));
3165+
ZEND_ASSERT(zend_string_equals_literal_ci(ZEND_TYPE_NAME(param->type), "self") || zend_string_equals_literal_ci(ZEND_TYPE_NAME(param->type), "parent"));
31633166
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(param->type));
3164-
resolved_type = (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_NAME(param->type), allows_null, /*extra flags */ 0);
3167+
resolved_type = (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_NAME(param->type), allows_null, /* extra flags */ 0);
31653168
}
31663169

31673170
reflection_type_factory(resolved_type, return_value, /* legacy_behavior */ true, intern->ce);
@@ -3203,14 +3206,7 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
32033206
} ZEND_TYPE_LIST_FOREACH_END();
32043207
} else if (ZEND_TYPE_HAS_NAME(param->type)) {
32053208
zend_string *name = ZEND_TYPE_NAME(param->type);
3206-
uint32_t type_flags = 0;
3207-
if (ZEND_TYPE_IS_RELATIVE_SELF(param->type)) {
3208-
type_flags = _ZEND_TYPE_SELF_BIT;
3209-
}
3210-
if (ZEND_TYPE_IS_RELATIVE_PARENT(param->type)) {
3211-
type_flags = _ZEND_TYPE_PARENT_BIT;
3212-
}
3213-
append_type(return_value, (zend_type) ZEND_TYPE_INIT_CLASS(name, /* allow_null */ false, /* extra flags */ type_flags), /* object_ce */ intern->ce);
3209+
append_type(return_value, (zend_type) ZEND_TYPE_INIT_CLASS(name, /* allow_null */ false, /* extra flags */ 0), /* object_ce */ intern->ce);
32143210
}
32153211

32163212
type_mask = ZEND_TYPE_PURE_MASK(param->type);

ext/reflection/tests/bug80190.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ foreach ((new ReflectionClass(C::class))->getMethods() as $method) {
4747
?>
4848
--EXPECT--
4949
C::a()
50-
$method->getReturnType() returns ReflectionRelativeClassType
51-
$method->getReturnType()->__toString() returns self
50+
$method->getReturnType() returns ReflectionNamedType
51+
$method->getReturnType()->__toString() returns C
5252

5353
C::b()
5454
$method->getReturnType() returns ReflectionUnionType
55-
$method->getReturnType()->__toString() returns stdClass|self
55+
$method->getReturnType()->__toString() returns stdClass|C
5656
$method->getReturnType()->getTypes() returns an array with 2 element(s)
57-
type(s) in union: ReflectionNamedType(stdClass), ReflectionRelativeClassType(self)
57+
type(s) in union: ReflectionNamedType(stdClass), ReflectionNamedType(C)
5858

5959
C::c()
6060
$method->getReturnType() returns ReflectionRelativeClassType

ext/reflection/tests/types/ReflectionType_001.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,12 @@ string(10) "SplSubject"
165165
bool(true)
166166
bool(false)
167167
bool(false)
168-
string(4) "self"
168+
string(1) "c"
169169
** Method 2 - parameter 0
170170
bool(true)
171171
bool(false)
172172
bool(false)
173-
string(6) "parent"
173+
string(8) "stdClass"
174174
** Method 3 - parameter 0
175175
bool(true)
176176
bool(false)
@@ -194,12 +194,12 @@ string(3) "int"
194194
bool(true)
195195
bool(false)
196196
bool(false)
197-
string(4) "self"
197+
string(1) "c"
198198
** Function/method return type 4
199199
bool(true)
200200
bool(false)
201201
bool(false)
202-
string(6) "parent"
202+
string(8) "stdClass"
203203
** Function/method return type 5
204204
bool(true)
205205
bool(false)

0 commit comments

Comments
 (0)