Skip to content

Commit d393268

Browse files
committed
Fixed bug #81582
If __toString() comes from a trait, implement Stringable during inheritance.
1 parent f22f4af commit d393268

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2021, PHP 8.0.14
44

5+
- Core:
6+
. Fixed bug #81582 (Stringable not implicitly declared if __toString() came
7+
from a trait). (Nikita)
8+
59
- GD:
610
. Fixed bug #71316 (libpng warning from imagecreatefromstring). (cmb)
711

Zend/tests/stringable_trait.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #81582: Stringable not implicitly declared if __toString() came from a trait
3+
--FILE--
4+
<?php
5+
6+
trait T {
7+
public function __toString(): string {
8+
return "ok";
9+
}
10+
}
11+
12+
class C {
13+
use T;
14+
}
15+
16+
var_dump(new C instanceof Stringable);
17+
18+
?>
19+
--EXPECT--
20+
bool(true)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
__toString() from trait with invalid return type
3+
--FILE--
4+
<?php
5+
6+
trait T {
7+
public function __toString(): int {
8+
return "ok";
9+
}
10+
}
11+
12+
class C {
13+
use T;
14+
}
15+
16+
var_dump(new C instanceof Stringable);
17+
18+
?>
19+
--EXPECTF--
20+
Fatal error: Declaration of T::__toString(): int must be compatible with Stringable::__toString(): string in %s on line %d

Zend/zend_inheritance.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,18 @@ ZEND_API zend_result zend_do_link_class(zend_class_entry *ce, zend_string *lc_pa
24852485
zend_verify_abstract_class(ce);
24862486
}
24872487

2488+
/* Normally Stringable is added during compilation. However, if it is important from a trait,
2489+
* we need to explicilty add the interface here. */
2490+
if (ce->__tostring && !zend_class_implements_interface(ce, zend_ce_stringable)) {
2491+
ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
2492+
ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
2493+
ce->num_interfaces++;
2494+
ce->interfaces = perealloc(ce->interfaces,
2495+
sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS);
2496+
ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable;
2497+
do_interface_implementation(ce, zend_ce_stringable);
2498+
}
2499+
24882500
zend_build_properties_info_table(ce);
24892501

24902502
if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) {

0 commit comments

Comments
 (0)