Skip to content

Commit a66272c

Browse files
committed
Add object variance support and test
1 parent cdda8b7 commit a66272c

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Testing object's variance in inheritance
3+
--FILE--
4+
<?php
5+
6+
interface I1 {
7+
function method1(I1 $o): object;
8+
}
9+
interface I2 extends I1 {
10+
function method1(object $o): I1;
11+
}
12+
final class C1 implements I2 {
13+
function method1($o = null): self {
14+
return $this;
15+
}
16+
}
17+
18+
$o = new C1();
19+
echo get_class($o->method1());
20+
?>
21+
--EXPECT--
22+
C1

Zend/zend_inheritance.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,24 +293,30 @@ int _check_inherited_arg_info(
293293
}
294294
}
295295
zend_string_release(proto_class_name);
296-
} else if (proto_type_code == IS_ITERABLE && variance == COVARIANT) {
297-
zend_class_entry * fe_ce = zend_lookup_class(fe_class_name);
298-
code = fe_ce && instanceof_function(fe_ce, zend_ce_traversable);
296+
} else if (variance == COVARIANT) {
297+
if (proto_type_code == IS_ITERABLE) {
298+
zend_class_entry * fe_ce = zend_lookup_class(fe_class_name);
299+
code = fe_ce && instanceof_function(fe_ce, zend_ce_traversable);
300+
} else if (proto_type_code != IS_OBJECT) {
301+
code = 0;
302+
}
299303
} else {
300304
code = 0;
301305
}
302306

303307
zend_string_release(fe_class_name);
304308
return code;
305309
} else if (ZEND_TYPE_IS_CLASS(proto_type)) {
306-
if (variance == CONTRAVARIANT && fe_type_code == IS_ITERABLE) {
307-
zend_string *proto_class_name =
308-
_resolve_parent_and_self(proto, ZEND_TYPE_NAME(proto_type));
309-
zend_class_entry *proto_ce = zend_lookup_class(proto_class_name);
310-
zend_string_release(proto_class_name);
311-
return proto_ce && instanceof_function(proto_ce, zend_ce_traversable);
312-
} else {
313-
return 0;
310+
if (variance == CONTRAVARIANT) {
311+
if (fe_type_code == IS_ITERABLE) {
312+
zend_string *proto_class_name =
313+
_resolve_parent_and_self(proto, ZEND_TYPE_NAME(proto_type));
314+
zend_class_entry *proto_ce = zend_lookup_class(proto_class_name);
315+
zend_string_release(proto_class_name);
316+
return proto_ce && instanceof_function(proto_ce, zend_ce_traversable);
317+
} else if (fe_type_code == IS_OBJECT) {
318+
return 1;
319+
}
314320
}
315321
} else if (fe_type_code == IS_ITERABLE || proto_type_code == IS_ITERABLE) {
316322
return (variance == COVARIANT && fe_type_code == IS_ARRAY)

0 commit comments

Comments
 (0)